Remove an image that was not put in uploads folder via wp_handle_upload

前端 未结 3 1127
长情又很酷
长情又很酷 2021-02-20 05:48

I\'m saving an image to uploads folder, but I\'m using file_put_contents instead of wp_handle_upload - because I get an image in base64 and not as a file in $_FILES.

Im

相关标签:
3条回答
  • 2021-02-20 05:57

    I actually accomplished this before I saw an answer here, so I'm providing a solution here if someone runs into the same problem. I used the function below (first one) and also using wp_delete_attachment after just to be sure all stuff got removed.

    /**
     * Attempt at removing all images in uploads folder by providing an image url 
     * Example: 
     *   - Provide http://mypage.com/wp-content/themes/mytheme/uploads/2015/12/testImage.jpg
     *   - this should remove all its images created when uploading:
     *   - testImage-150x150.jpg, testImage-300x300.jpg etc and also the provided original image 
     *
     * We'r doing this because wp_delete_attachment() will not remove an image that was uploaded via a 
     * custom mytheme_upload_image() function (which is providing base64 image instead of file in $_FILES)
     *
     * TODO TODO mytheme_get_image_sizes() does not return ALL IMAGES THAT WERE CREATED (all sizes)
     */
    function mytheme_remove_all_image_sizes_from_uploads($primary_image_url) {
    
        $pi = pathinfo($primary_image_url);
    
        $img_dirname = $pi['dirname'];
        $img_dirname_exploded = explode('/',$img_dirname);   
        $last_dir = array_pop($img_dirname_exploded); // month usually (two digits)
        $second_last_dir = array_pop($img_dirname_exploded); // year usually (4 digits)
    
        $basename = $pi['basename']; // without trailing /
        $img_name = $pi['filename'];
        $img_extension = $pi['extension'];
    
        $uploads = wp_upload_dir();
        $base_uploads_dir = $uploads['basedir']; // without trailing /
    
        $path_to_appropriate_uploads_dir =      $base_uploads_dir.'/'.$second_last_dir.'/'.$last_dir.'/';
    
        $img_name_to_remove = $img_name.'.'.$img_extension; // UNLINK
    
        if(!@unlink($path_to_appropriate_uploads_dir.$img_name_to_remove)) {
           // this image was not removed
        }
    
        $image_sizes = mytheme_get_image_sizes();
    
        foreach($image_sizes as $size) {
           $img_name_to_remove = $img_name.'-'.$size.'.'.$img_extension; // UNLINK
           $img_path = $path_to_appropriate_uploads_dir.$img_name_to_remove;
    
           if(mytheme_image_on_url_exists($img_path) && !@unlink($img_path)) {
              // this image was not removed
           }
        }
    
     }
    
    
        /**
     * Get size information for all currently-registered image sizes.
     * Found an example of this on one of the wordpress' example pages ..
     *
     * @global $_wp_additional_image_sizes
     * @uses   get_intermediate_image_sizes()
     * @return array $sizes Data for all currently-registered image sizes.
     * TODO TODO mytheme_get_image_sizes() does not return ALL IMAGES THAT WERE CREATED (all sizes)
     */
    function mytheme_get_image_sizes() {
        global $_wp_additional_image_sizes;
    
        $sizes = array();
    
        foreach ( get_intermediate_image_sizes() as $_size ) {
    
            if ( in_array( $_size, array( 'thumbnail', 'medium', 'large' ) ) ) {
    
                $width = get_option( "{$_size}_size_w" );
                $height = get_option( "{$_size}_size_h" );
    
            } elseif ( isset( $_wp_additional_image_sizes[ $_size ] ) ) {
    
                $width = $_wp_additional_image_sizes[ $_size ]['width'];
                $height = $_wp_additional_image_sizes[ $_size ]['height'];
    
            }
    
            $img_name_end = $width."x".$height;
    
            if(!in_array($img_name_end,$sizes)) {
                $sizes[] = $img_name_end;
            }
    
        }
    
        // ADD CUSTOM SIZES (this one is not returned otherwise?!)
        $sizes[] = '300x200';
    
        return $sizes;
    }
    
    0 讨论(0)
  • 2021-02-20 06:01

    The simple solution is probably to just manually add _wp_attached_file meta value to your attachment.

    Set it to the file you want deleted when the attachment is deleted.

    The logic behind this is according to https://core.trac.wordpress.org/browser/tags/4.4/src/wp-includes/post.php#L0:

    get_attached_file returns that value to wp_delete_attachment which sets it as $file

    And at the end of wp_delete_attachment it calls wp_delete_file($file)

    So I'm guessing the underlying issue is that, you are never setting a value for the meta key _wp_attached_file.

    The only downside is that I'm not sure what other processes in wp might be using that value. But you might get lucky, perhaps none, and/or it doesn't mess anything up by setting it manually.

    0 讨论(0)
  • 2021-02-20 06:14

    as @KamilP said, WP inserts records in wp_posts and wp_postmeta tables.

    So first you have to save your base64 images in temporary directory, then by using it's relative path and other data you can insert record in database by using wp_insert_attachment, link contains appropriate example. This function will add image to media library.

    To generate more thumbnails you can use wp_generate_attachment_metadata function. This function will update wp_postmeta table also with all details of image and thumbnails.

    After this you can use wp_delete_attachment function to delete image from directory and database as well.

    Another solution:

    • Use function from this link to generate image from base64 string.
    • then get mime type, size and path of image
    • create an array similar to $_FILES's.
    • then pass it to wp_handle_upload

    UPDATE :

    $_FILES array's structure is like this

    array(5) {
        'name'     => string(8) "file name.extension" // file name with extension
        'type'     => string(0) "" // mime type of file, i.e. image/png
        'tmp_name' => string(0) "" // absolute path of file on disk.
        'error'    => int(2) // 0 for no error
        'size'     => int(0) // size in bytes
      }
    

    You can create array like above with all details, use various file handling PHP functions to get size and mime type. Name is whatever you want to put, and tmp_name is a path of file on server where file is exists, in your case location of folder where you save your file from base64 string.

    See updated link above for function which will give you image from base64 string.

    0 讨论(0)
提交回复
热议问题