通过 wp_handle_upload 删除未放入上传文件夹的图像

Posted

技术标签:

【中文标题】通过 wp_handle_upload 删除未放入上传文件夹的图像【英文标题】:Remove an image that was not put in uploads folder via wp_handle_upload 【发布时间】:2016-02-17 11:05:45 【问题描述】:

我正在将图像保存到上传文件夹,但我使用的是 file_put_contents 而不是 wp_handle_upload - 因为我在 base64 中获得了图像,而不是作为 $_FILES 中的文件。

图像和某些帖子数据被保存/更新,因为它们应该使用此功能:

wp_insert_attachment wp_update_attachment_metadata

问题是当我想删除旧图像时(保存新图像时)。

wp_delete_attachment 不会删除图像(尽管它似乎确实删除了 db 中的东西..)。我认为问题在于不使用 wp_handle_upload。 (当我通过上传 btn 上传图像并使用 $_FILES 接收它然后使用 wp_handle_upload 上传时 - 删除作品)

有没有人知道在我的情况下删除图像的正确方法是什么? 也许我可以使用 wp_handle_upload 正确保存它,即使我有 base64 中的图像?

感谢您提供任何信息。

编辑:我还尝试使用 wp_upload_bits 保存图像,但 wp_delete_attachment 仍然无效。

我检查的另一件事:位于 wp-admin/includes/file.php 的 wp_handle_upload 函数的 the code:我没有看到一种简单的方法来修改或复制现有函数并添加一个自定义函数,该函数将接受 base64 图像而不是文件作为在 $_FILES 中。也许有人有“base64 to $_FILES”的解决方法?

【问题讨论】:

第一件事 - 检查数据库。如果您使用 wp_handle_upload 上传普通文件,Wordpress 会在您的数据库中创建一些记录?也许 WP 无法删除此图像,因为您在数据库中没有任何记录。其他方式 - 因为您手动保存图像(使用 file_put_contents),您可以手动删除它(在 PHP 中取消链接)。 我在考虑使用 unlink,但这不是一个很好的解决方案,因为您必须调用多个 unlinks(所有拇指等)。不知何故需要获取为每个上传的 img 创建的所有缩略图 .. 嗯。并且这些缩略图可能在名称/文件夹中有一些模式,或者 Wordpress 将有关缩略图的这些信息保存在数据库中。也许您可以编写自己的函数来上传。有wp_handle_upload,你可以创建wp_handle_base64_upload,它可以是wp_handle_upload的副本,你可以在你自己的函数中做同样的事情。检查 wp_handle_upload 在哪里。 也想一想:问题是 wp_handle_upload 接受 $file,其中(我引用)“$file 对 $_FILES 的单个元素的引用。为每个上传的文件调用一次函数。” 嗯...也许你可以在上传之前执行一些函数并覆盖$_FILES。我不确定,但我知道你可以替换 $_POST,所以也可能替换为 $_FILES。您可以过滤每个文件并将其放入 $_FILES。 【参考方案1】:

正如@KamilP 所说,WP 在wp_postswp_postmeta 表中插入记录。

所以首先你必须将你的base64图像保存在临时目录中,然后使用它的相对路径和其他数据,你可以使用wp_insert_attachment在数据库中插入记录,链接包含适当的示例。 此函数将图像添加到媒体库。

要生成更多缩略图,您可以使用wp_generate_attachment_metadata 函数。此函数还将使用图像和缩略图的所有详细信息更新 wp_postmeta 表。

之后你可以使用wp_delete_attachment函数从目录和数据库中删除图片。

另一种解决方案:

使用this link 中的函数从base64 字符串生成图像。 然后获取图像的 mime 类型、大小和路径 创建一个类似于 $_FILES 的数组。 然后将其传递给wp_handle_upload

更新:

$_FILES 数组的结构是这样的

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
  

您可以像上面一样创建包含所有详细信息的数组,使用各种文件处理 PHP 函数来获取大小和 mime 类型。名称是您要放置的任何内容,而 tmp_name 是文件所在服务器上的文件路径,在您的情况下是从 base64 字符串保存文件的文件夹位置。

请参阅上面的更新链接以获取来自 base64 字符串的图像。

【讨论】:

如何在给定 base64 img 的情况下正确创建类似的数组 ($_FILES)?我已经事先得到了 mime-type 和 size .. 所以这不应该是一个问题.. 你确定 wp_handle_upload 会接受'假'$_files吗?【参考方案2】:

我实际上是在我在这里看到答案之前完成了这个,所以如果有人遇到同样的问题,我会在这里提供一个解决方案。我使用了下面的函数(第一个)并使用 wp_delete_attachment after 只是为了确保所有东西都被删除了。

/**
 * 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;

【讨论】:

【参考方案3】:

简单的解决方案可能是手动将_wp_attached_file 元值添加到附件中。

设置为删除附件时要删除的文件。

这背后的逻辑是根据https://core.trac.wordpress.org/browser/tags/4.4/src/wp-includes/post.php#L0:

get_attached_file 将该值返回给wp_delete_attachment,将其设置为$file

wp_delete_attachment 的末尾,它调用wp_delete_file($file)

所以我猜测根本问题是,您永远不会为元键 _wp_attached_file 设置值。

唯一的缺点是我不确定 wp 中的哪些其他进程可能正在使用该值。但是你可能会很幸运,也许没有,和/或手动设置它不会搞砸任何事情。

【讨论】:

以上是关于通过 wp_handle_upload 删除未放入上传文件夹的图像的主要内容,如果未能解决你的问题,请参考以下文章

如何将Linux rm命令删除的文件放入垃圾箱

git如何删除已经 add 的文件 (如何撤销已放入缓存区文件的修改)

全文搜索未通过删除字符串字体中的字符来查找结果

Fetch Api - 删除 - 对预检请求的响应未通过访问控制检查

通过压缩和修复从 Cassandra db 中删除大量数据后,磁盘空间未更改

将@EnableConfigServer注解放入spring boot后未启用Swagger