分块上传验证:“无法上传文件。”

Posted

技术标签:

【中文标题】分块上传验证:“无法上传文件。”【英文标题】:Chunked upload validation: "The file could not be uploaded." 【发布时间】:2021-08-14 17:16:01 【问题描述】:

我目前正在尝试让 Symfonys Validator 组件处理上传文件的验证,这对于普通文件非常有效。但是,如果文件超过一定大小,它们将作为块上传,然后合并并验证。两种上传方式都由同一个函数验证,基本上就是这样:

public function validateFile(UploadedFile $uploadedFile): ConstraintViolationList 

    return $this->validator->validate(
        $uploadedFile,
        [
            new FileConstraints([
                'maxSize' => '1000M',
            ]),
        ]
    );

但不知何故,合并的上传触发了违规,不幸的是,这对我来说是非常无信息的:

Symfony\Component\Validator\ConstraintViolation #658 ▼
  -message: "The file could not be uploaded."
  -messageTemplate: "The file could not be uploaded."
  -parameters: []
  -plural: null
  -root: Symfony\Component\HttpFoundation\File\UploadedFile #647 ▶
  -propertyPath: ""
  -invalidValue: Symfony\Component\HttpFoundation\File\UploadedFile #647 ▶
  -constraint: Symfony\Component\Validator\Constraints\File #649 ▶
  -code: "0"
  -cause: null

日志很干净,没有错误,只有关于匹配路由和弃用内容的信息以及关于身份验证令牌等的调试。

如果我转储 UploadedObjects,唯一的区别是分块和合并的对象具有executable: true,并且它没有存储在 tmp 中。

这里有人可以向我解释导致这种违规行为的原因以及必须采取哪些措施来防止这种违规行为,或者向我指出一些相关的文档吗?

编辑:块的上传和合并似乎工作得非常好 - 可以查看上传的图像,可以阅读文本文档/pdf等。现在还使用了所有其他代码很长一段时间进行不同的验证,只是想要通过使用现有的 Validator 基础设施,让一切变得更加专业和有序。要提供有关已上传对象的其他信息,这里是 dd 输出,从常规文件上传开始:

Symfony\Component\HttpFoundation\File\UploadedFile #20 ▼
  -test: false
  -originalName: "foo.jpg"
  -mimeType: "image/jpeg"
  -error: 0
  path: "/tmp"
  filename: "phpEu7Xmw"
  basename: "phpEu7Xmw"
  pathname: "/tmp/phpEu7Xmw"
  extension: ""
  realPath: "/tmp/phpEu7Xmw"
  aTime: 2021-05-27 10:47:56
  mTime: 2021-05-27 10:47:54
  cTime: 2021-05-27 10:47:54
  inode: 1048589
  size: 539474
  perms: 0100600
  owner: 1000
  group: 1000
  type: "file"
  writable: true
  readable: true
  executable: false
  file: true
  dir: false
  link: false

对于分块上传:

Symfony\Component\HttpFoundation\File\UploadedFile #647 ▼
  -test: false
  -originalName: "foo.jpg"
  -mimeType: "image/jpeg"
  -error: 0
  path: "/home/vagrant/MyProject/var/uploads"
  filename: "foo.jpg"
  basename: "foo.jpg"
  pathname: "/home/vagrant/MyProject/var/uploads/foo.jpg"
  extension: "jpg"
  realPath: "/home/vagrant/MyProject/var/uploads/foo.jpg"
  aTime: 2021-05-27 10:43:58
  mTime: 2021-05-27 10:43:58
  cTime: 2021-05-27 10:43:58
  inode: 8154
  size: 539474
  perms: 0100777
  owner: 1000
  group: 1000
  type: "file"
  writable: true
  readable: true
  executable: true
  file: true
  dir: false
  link: false

【问题讨论】:

这可能有不同的原因。我建议您遵循以下想法: 1. 如果您有任何日志,请提供任何日志。 2. 在调试时进入这个类,看看里面发生了什么。 3. 尝试使用 maxSize 可能会导致异常。 @DariusMann 感谢您的帮助!日志中没有错误或类似情况,只有匹配块上传和合并路由的信息,并且不推荐使用某些内容以及有关身份验证的调试输出。我已经玩过 maxSize 了。没有帮助,但如果 maxSize 太低,它仍然会失败,并显示“无法上传文件”。而不是与最大尺寸相关的消息,所以我猜它表明触发违规的检查出现在 maxSize 检查之前。关于 2. - 你的意思是哪个班级?约束类? 你确定所有的块都被正确上传和重组了吗?您是否手动检查了生成的文件?在我看来,生成的文件已以某种方式重命名,但需要更多细节。 @msg 再次感谢您的帮助!我编辑了我的帖子以提供更多详细信息(是的,文件是手动测试的) @msg 天哪,你成功了。通过删除is_uploaded 检查对其进行了测试,它工作正常。所以我必须合并 /tmp 中的块,然后再移动文件。非常感谢,这将是公认的答案! 【参考方案1】:

File 约束接收到UploadedFile 实例时,它会触发对isValid 的调用,而isValid 又会调用is_uploaded_file

如果 filename 命名的文件是通过 HTTP POST 上传的,则返回 true。 这有助于确保恶意用户没有尝试 诱使脚本处理不应该处理的文件 工作

在将块重新组装成新文件后,此检查不再通过并且约束失败。

您可以使用最后一个文件片段来重新组装原始文件,或者您可以从您的函数返回FileFile 不受该检查的约束,约束将与 UploadedFile 一起接受它。

【讨论】:

【参考方案2】:
new Count([
  'min' => 1,
  'minMessage' => 'Please select a file to upload'
]),

我认为NotBlank 约束是这里的问题,我认为它不应该用于UploadedFile

尝试仅使用 FileCount 约束(以确保至少附加 1 个文件)。

【讨论】:

感谢您的提示 :) 不幸的是,NotBlank 不是问题,由于尝试和错误,我已经知道是导致问题的 FileConstraint。我将进行编辑以明确说明! 是的,我的错误只是检查了属于文件的约束违规。你能在这一行显示完整的约束错误吗? ` -constraint: Symfony\Component\Validator\Constraints\File #649 ▶`【参考方案3】:

以编程方式创建 UploadedFile 对象时,请使用“测试模式”。我将它与 VichUploaderBundle 一起使用,并记录了测试模式的使用 here。

【讨论】:

以上是关于分块上传验证:“无法上传文件。”的主要内容,如果未能解决你的问题,请参考以下文章

Linux文件无法删除文件,也无法上传文件

由于大小无法上传文件

Titanium HTTPCLIENT 无法上传文件

Fine Uploader 无法上传文件

php环境无法上传文件的解决方法

Autodesk Forge uploadObject API 无法上传文件 30MB 到 100MB 文件