lsky-org / lsky-pro

☁️兰空图床(Lsky Pro) - Your photo album on the cloud.
https://www.lsky.pro
GNU General Public License v3.0
4.16k stars 612 forks source link

通过 API 删除图片,接口返回成功,但是实际并没有被删除 #366

Closed hellodk34 closed 2 years ago

hellodk34 commented 2 years ago

首先感谢大佬开发兰空图床,非常好用,谢谢。

前几天写了一个 PicGo 插件适配了兰空图床 V1 和 V2 https://github.com/hellodk34/picgo-plugin-lankong

今天在做 PicGo 相册中同步删除功能时,发现调用 API 成功,但是实际上图片并没有被删除。

20220330171809

通过 postman 之类的工具调用删除接口 status 返回了 true,而且多次调用均返回了 true(不应该只允许一次 true 么),源图床站使用了 cdn,但是多次调用 status 依然 true ?

在 web 页面上主动删除一张图片通过 F12 发现调用了 /user/images 接口,公开 API 是 /api/v1/images/:KEY,两个也不一样,想知道我这是哪里出了问题,还是 Lsky Pro V2 删除 API 有 bug?

wisp-x commented 2 years ago

使用的是七牛云储存吗?

hellodk34 commented 2 years ago

尚不清楚使用的什么 cdn,源图床站是 https://dogimg.com/

我拿我自己部署的试试,套的 cf cdn

wisp-x commented 2 years ago

如果是七牛云储存,删除图片目前是有问题的,详细:https://github.com/lsky-org/lsky-pro/issues/331#issuecomment-1070337651 程序删除操作永远都是返回成功的状态,目的是避免修改、删除了储存策略配置导致删除失败的问题。如果发现物理图片没有删除成功,正常情况下在程序 storage/logs 目录里可以找到详细的错误日志。

hellodk34 commented 2 years ago

好的,谢谢指出,晚上回去我再看看日志,刚刚用我自己部署的测试也似乎是没有删掉,晚上回去看一下日志。有问题我再反馈,感谢你飞快的回复。💗️

hellodk34 commented 2 years ago

20220330203033

我在自己的服务器上测试,删除前查到文件在服务器上,成功调用删除接口后文件依然在原位置。

storage/logs/laravel-2022-03-23.log 日志里似乎没有什么有用的信息

[2022-03-23 11:43:24] prod.ERROR: Api 上传文件时发生异常 {"file":"/var/www/html/vendor/intervention/image/src/Intervention/Im     age/AbstractDecoder.php","line":351,"message":"Image source not readable","trace":"#0 /var/www/html/vendor/intervention/image     /src/Intervention/Image/AbstractDriver.php(66): Intervention\\Image\\AbstractDecoder->init(NULL)

...

#32 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Barryvdh\\Debugbar\\Middleware\\InjectDebugbar->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#33 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#34 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ConvertEmptyStringsToNull.php(31): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#35 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\\Foundation\\Http\\Middleware\\ConvertEmptyStringsToNull->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#36 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#37 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php(40): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#38 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\\Foundation\\Http\\Middleware\\TrimStrings->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#39 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php(27): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#40 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#41 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(86): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#42 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#43 /var/www/html/vendor/fruitcake/laravel-cors/src/HandleCors.php(52): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#44 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Fruitcake\\Cors\\HandleCors->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#45 /var/www/html/vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php(39): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#46 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\\Http\\Middleware\\TrustProxies->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#47 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(116): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#48 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(142): Illuminate\\Pipeline\\Pipeline->then(Object(Closure))
#49 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(111): Illuminate\\Foundation\\Http\\Kernel->sendRequestThroughRouter(Object(Illuminate\\Http\\Request))
#50 /var/www/html/public/index.php(52): Illuminate\\Foundation\\Http\\Kernel->handle(Object(Illuminate\\Http\\Request))
#51 {main}"}
hellodk34 commented 2 years ago

20220330204525

20220330204551

删除时是使用上传成功后返回的 data.key

wisp-x commented 2 years ago

删除时是使用上传成功后返回的 data.key

是的,另外删除物理文件的前提条件是不存在其他相同 md5、sha1 值的文件记录,程序为了节省空间占用,上传相同的图片不会重复创建物理文件,所以系统中可能会出现多条记录指向同一个文件。

hellodk34 commented 2 years ago

好的,谢谢指教。但是我这个问题我不知道该如何排查了……

wisp-x commented 2 years ago

@hellodk34 目前还未遇到本地储存无法删除文件的情况,你可以试一下上传图床里不存在的图片,然后看一下图片的权限,无论是接口删除还是通过 web 删除,删除方式都是一样的没有差异,顺便在看一下该图片的缩略图有没有被删除成功。如果不是上述我所说的多个纪录指向同一个文件的原因,那大概率就是因为权限导致的无法删除了。

所以系统中可能会出现多条记录指向同一个文件

如果有这个情况出现,删除其中某一个文件记录,不会删除物理文件。

hellodk34 commented 2 years ago

@wisp-x 权限是 755,owner 和 group 都是 www-data,刚刚通过 web 删除文件成功,但是其缩略图并没有被删掉。通过接口调用,文件和缩略图都没有被删掉。

ps: 我通过 web 删除了图片并没有触发 我的图片 自动刷新,是 nginx 或 apache 配置问题吗?

wisp-x commented 2 years ago

@hellodk34 看描述很玄学,不清楚什么问题。

hellodk34 commented 2 years ago

@wisp-x 感谢这么晚一直追踪问题。有空你也可以自己尝试一下,可以用这个图床 然后还有我写的适配兰空图床的 PicGo 图片上传插件 🙏🏻

hellodk34 commented 2 years ago

看描述很玄学,不清楚什么问题。

@wisp-x 回头重新部署一个看看,这次部署是根据别人的一个不成熟的 Docker 镜像装的。

HalcyonAzure commented 2 years ago

看描述很玄学,不清楚什么问题。

@wisp-x 回头重新部署一个看看,这次部署是根据别人的一个不成熟的 Docker 镜像装的。

我今天试了下我在issues里面发的Docker容器,通过您的PicGo插件删除确实复现了同样的问题。不过同样的文件我通过Postman调用接口的时候成功删除了

重新测试了下,在用Docker进行部署测试的时候大致有三种情况:

  1. 在Web界面当中直接删除,网页中的图片正常删除消失,本地uploads下对应的文件同样被删除
  2. 用Postman发送图片并删除之后,在网页显示正常删除消失,但是本地uploads下对应的文件并未被删除
  3. 在使用您开发的插件中启用SyncDelete并删除后,PicGo后台提示删除成功,但是网页显示和本地后台文件均未删除

不排除有我个人因为刚接触工具不熟悉的情况导致的失误 :confused:

hellodk34 commented 2 years ago

@HalcyonAzure 感谢你帮忙测试。

20220330171809

PicGo lankong 插件 SyncDelete 选项打开同步删除图床文件就是调用的删除图片 api(和上面使用 postman 工具调用删除接口一样),各种参数我也确认过好几遍,接口也返回了 true,就是没能删除图片。暂时还不太清楚是为何没有删除成功(抽空再检查一下代码与 api 说明页面认真核对下。

至于你有说

用Postman发送图片并删除之后,在网页显示正常删除消失,但是本地uploads下对应的文件并未被删除

这好像也很怪 😿️

hellodk34 commented 2 years ago

@HalcyonAzure 请教一下我用 postman 调 API 上传文件总是遇到错误

Warning: Missing boundary in multipart/form-data POST data in Unknown on line 0
{"status":false,"message":"\u670d\u52a1\u5f02\u5e38\uff0c\u8bf7\u7a0d\u540e\u518d\u8bd5","data":{}}

是怎么回事?req headerContent-Type 已经指定成了 multipart/form-data 了,费解啊

postman upload image.png

我自己的 Lsky Pro V2 站

换了 dogimg 点 com 也无法通过 api 上传,不过错误信息不同

dogimg.png

dogimg 点 com

感觉和前置的反向代理服务器有关,比如我的用了 nginx ,nginx 配置不当。或者容器内的 php 或 Apache 配置不当 (本人不是很了解 php 和 Apache -_-)

HalcyonAzure commented 2 years ago

@hellodk34 我的Postman设置大致如下 Authorization: image Headers: image 其中 Content-Typemultipart/form-data; charset=utf-8; boundary=+ Math.random().toString().substr(2)) Acceptapplication/json, text/javascript, */*; q=0.01 Body: image 发送成功后返回的内容大致为: image

HalcyonAzure commented 2 years ago

@HalcyonAzure 请教一下我用 postman 调 API 上传文件总是遇到错误

Warning: Missing boundary in multipart/form-data POST data in Unknown on line 0
{"status":false,"message":"\u670d\u52a1\u5f02\u5e38\uff0c\u8bf7\u7a0d\u540e\u518d\u8bd5","data":{}}

是怎么回事?req headerContent-Type 已经指定成了 multipart/form-data 了,费解啊

postman upload image.png

我自己的 Lsky Pro V2 站

换了 dogimg 点 com 也无法通过 api 上传,不过错误信息不同

dogimg.png

dogimg 点 com

感觉和前置的反向代理服务器有关,比如我的用了 nginx ,nginx 配置不当。或者容器内的 php 或 Apache 配置不当 (本人不是很了解 php 和 Apache -_-)

另外上图发的两个报错应该是相同内容,“\u670d\u52a1\u5f02\u5e38\uff0c\u8bf7\u7a0d\u540e\u518d\u8bd5”这个用Unicode转码为中文后对应的内容就是"服务异常,请稍后再试",我自己昨天遇到这个报错后Google搜了下,在Content-Type加上charset=utf-8; boundary=+ Math.random().toString().substr(2))就可以自动转码成中文了 XD

hellodk34 commented 2 years ago

@HalcyonAzure

Content-Type 加上 charset=utf-8; boundary=+ Math.random().toString().substr(2)) 就可以自动转码成中文了

确实如此,感谢。

我上面使用的是 insomnia 和 vscode 里的扩展 Thunder Client,,刚刚我重新下载回 Postman 上传了一遍,居然一直 400 bad request, 我不知道哪里出了问题,和你的配置完全一样,可能是 nginx 配置问题。

wisp-x commented 2 years ago

@hellodk34 @HalcyonAzure 很抱歉,这是程序中的一个 bug,目前已修复,将在下个版本中发布。

hellodk34 commented 2 years ago

实际上我还没测试到 通过接口调用删除图片 API,web 上图片成功消失但物理文件并没有被删除 这个地步。原因是我使用 postman 或 lankong 插件调用删除图片接口时写错了 URL。

20220401170449

感谢 @HalcyonAzure 的帮助,更感谢兰空作者大大的工作。👍🏻

现 PicGo 插件 lankong 已发布 v1.0.6,可实现同步删除。

hellodk34 commented 2 years ago

ps: 我通过 web 删除了图片并没有触发 我的图片 页面自动刷新,是 nginx 或 apache 配置问题吗?

之前版本是 V2,现在升级到了 V2.0.3 不存在这个问题了(之前 2.0 最初的版本可能有问题,现在最新版没有问题,非常棒)。