Laravel 8文件上传验证失败,无论规则是什么

5

我想验证文件上传,但是无论使用哪种验证规则,都会出现 "(输入框名称)上传失败" 的提示。我在一些地方看到了这个问题,但是没有一个解决方案适用于我。

我正在使用 Laravel 8.0、php 8.0.2 和 ubuntu 上的 nginx/1.18.0。

控制器:

public function uploadMedia (Request $request)
{
    $request->validate([
        'file' => 'required',
        'alt' => 'required',
    ]);
    dd('valid');
}

Blade文件:

@if($errors->any())
    @foreach ($errors->all() as $error)
        <p class="alert error">{{ $error }}</p>
    @endforeach
@endif

<form method="POST" action="/media" enctype="multipart/form-data">
    @csrf
    <input type="file" name="file" />
    <input type="text" name="alt" placeholder="Write a short description of the image under 160 characters." />
    <button type="submit">Upload</button>
</form>

如果我删除“file”的验证规则,它可以正常工作,然后我就可以到达dd。
$request->validate([
    'file' => '', // works if I do this
    'alt' => 'required',
]);

我看到其他人遇到了同样的问题,我尝试过:

  • 用另一个规则 (max:10000,image) 替换 'required' – 仍然出现相同的错误。
  • 将 php.ini 的值更改为post_max_size = 201Mupload_max_filesize = 200M (这本来不应该成为问题,因为我尝试上传的图片是一个136kb的jpg)。通过phpinfo();核实
  • 更改这些值后,重新加载nginx和php-fpm
  • 重启虚拟机
  • 检查所有双引号和单引号是否正确
  • 尝试上传其他文件类型,如PNG或TXT,仍然出现相同的错误
  • 将'image'作为第一个验证规则,这对某人在这里起作用
  • 删除规则数组末尾的额外逗号
  • 将文件输入的名称更改为除'file'之外的其他内容
  • 使用不同的浏览器 (Firefox和Chrome)
  • 禁用所有浏览器扩展程序
  • 像这样编写验证 (仍然出现相同的错误):
$validator = Validator::make($request->all(), [
    'file' => 'required',
    'alt' => 'required'
]); 
if ($validator->fails()) {
    return redirect('/media')->withErrors($validator);
}

如果在验证之前使用dd($request):

Illuminate\Http\Request {#44 ▼
  #json: null
  #convertedFiles: null
  #userResolver: Closure($guard = null) {#255 ▶}
  #routeResolver: Closure() {#264 ▶}
  +attributes: Symfony\Component\HttpFoundation\ParameterBag {#46 ▶}
  +request: Symfony\Component\HttpFoundation\ParameterBag {#45 ▼
    #parameters: array:2 [▼
      "_token" => "RrjAA2YvnSd3EYqg8vAwoWT4y6VenJzGjb5S72SU"
      "alt" => "dsfghdf"
    ]
  }
  +query: Symfony\Component\HttpFoundation\InputBag {#52 ▶}
  +server: Symfony\Component\HttpFoundation\ServerBag {#49 ▶}
  +files: Symfony\Component\HttpFoundation\FileBag {#48 ▼
    #parameters: array:1 [▼
      "file" => Symfony\Component\HttpFoundation\File\UploadedFile {#33 ▼
        -test: false
        -originalName: "Screen Shot 2021-03-08 at 9.33.19 AM.png"
        -mimeType: "application/octet-stream"
        -error: 6
        path: ""
        filename: ""
        basename: ""
        pathname: ""
        extension: ""
        realPath: "/var/www/[my domain]/public"
        aTime: 1970-01-01 00:00:00
        mTime: 1970-01-01 00:00:00
        cTime: 1970-01-01 00:00:00
        inode: false
        size: false
        perms: 00
        owner: false
        group: false
        type: false
        writable: false
        readable: false
        executable: false
        file: false
        dir: false
        link: false
      }
    ]
  }
  +cookies: Symfony\Component\HttpFoundation\InputBag {#47 ▶}
  +headers: Symfony\Component\HttpFoundation\HeaderBag {#50 ▶}
  #content: null
  #languages: null
  #charsets: null
  #encodings: null
  #acceptableContentTypes: null
  #pathInfo: "/media"
  #requestUri: "/media"
  #baseUrl: ""
  #basePath: null
  #method: "POST"
  #format: null
  #session: Illuminate\Session\Store {#296 ▶}
  #locale: null
  #defaultLocale: "en"
  -preferredFormat: null
  -isHostValid: true
  -isForwardedValid: true
  -isSafeContentPreferred: null
  basePath: ""
  format: "html"
}

你能展示一下你的数据字典请求和存储函数吗? - sd077
你是否已经为上传文件的文件夹设置了适当的读写权限? - OMi Shah
我实际上并没有对文件进行任何操作,只是尝试验证它,如果成功则输出“valid”。如果我删除“file”输入的规则,我可以得到想要的结果,因此我认为问题不在于文件处理? - camille
好的,我会在原始帖子中发布。 - camille
仅因为您没有对文件执行任何操作,并不意味着Laravel也没有。上传的文件显示为空对象的事实意味着将上传的文件保存到临时目录中遇到了问题,权限很可能是最常见的问题。 - miken32
显示剩余6条评论
1个回答

1
错误值6表示UPLOAD_ERR_NO_TMP_DIR。请确保您的系统具有正确配置的上传临时目录,方法是从命令行运行php -i(或从网页运行phpinfo();),并检查upload_tmp_dir key。在典型的Linux系统上,这将类似于/tmp。如果需要,可以在php.ini中设置该值。确保列出的文件夹的权限正确,以便Web服务器进程被允许写入它。

不要尝试使用您的公共可访问文件夹作为上传目录(例如直接保存到storage/app/public或类似文件夹)。您的应用程序代码应该像文档中描述的那样将文件移动到存储文件夹;例如:

public function uploadMedia(Request $request)
{
    $request->validate([
        'file' => ['required', 'file', 'image'],
        'alt' => ['required', 'string'],
    ]);
    $path = $request->file->store('images');
    return redirect()->route('whatever')->with('success', "File saved to $path");
}

非常感谢,设置一个临时上传目录起作用了!我正在使用不同的open_basedir为每个应用程序设置php-fpm池,因此我实际上必须在我的池配置中使用我找到的变量设置tmp目录值,链接在这里,它起作用了!然而,由于我将open_basedir设置为我的应用程序根目录,因此该应用程序无法访问其目录之外的内容,因此为使其正常工作,临时目录必须位于我的应用程序根目录中。我不确定如何使我的临时目录不在我的应用程序根目录中,而不会取消此规则? - camille
抱歉如果不太清楚,以下是我的 phpfpm 池配置,让它能够正常工作,但我不确定如何使我的临时目录位于 basedir 之外... php_admin_value[open_basedir] = "/var/www/(app root)" php_admin_value[upload_tmp_dir] = "/var/www/(app root)/tmp" - camille
在你的应用程序根目录下没问题,我是指公共文件夹。我会澄清答案。 - miken32
我最关心的是从dd()输出中看到realPath: "/var/www/[my domain]/public" - miken32
啊,好的,明白了!谢谢你的帮助。 - camille

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接