Laravel 5.1:将上传的文件保留为旧输入

30

我正在使用 Laravel 5.1 中的表单来发布一些文本并上传文件。它看起来像这样(简化版本):

{!! Form::open(array('url' => 'foo/bar')) !!}
    {!! Form::text('image_name') !!}
    {!! Form::file('image') !!}
    {!! Form::submit('Submit!') !!}
{!! Form::close() !!}

该文本字段为必填项,因此我在控制器中添加了$validator。如果验证失败,用户将被重定向回表单页面。我使用withInput()方法来重新填充表单,以便用户不必再次填写:

if ($validator->fails()) {
    return redirect()->back()->withInput();
}

这将使文本框,下拉列表等恢复旧输入。但是如果用户上传了文件,则在验证失败时文件选择将消失,必须重新选择。在Laravel中有没有一种方法可以记住文件选择作为旧输入?

谢谢!


1
出于安全性和复杂性的原因,我认为你不能这样做 - 不仅仅是在Laravel中,而是一般情况下都不行。 - Tim Lewis
3个回答

78
不,file输入框不能被Laravel或其他软件预填充。你的网站(以及任何网站)都不应该知道文件的本地路径。如果知道了,想象一下安全风险!你可能会欺骗用户上传他们的SSH私钥或其他文件。
你需要做的是无论如何都要处理已上传的文件,即使有验证错误也要这样做。
然后,你可以将其存储在数据库中,并带有pending状态,或者为其分配一个唯一的hash,并将匹配的hash存储在用户的会话中。重点是能够识别属于特定用户的不完整上传文件。
然后,在显示表单时,从会话或数据库中检索这些不完整的文件,并在文件上传旁边显示缩略图。这告诉用户他们不需要重新上传该文件。只需确保他们有一种方法来删除它,以防他们改变主意。
一旦表单正确提交,然后清除会话的hash或将数据库状态更新为complete;做任何你需要做的事情。

谢谢您提供这么清晰的答案,我完全明白了。我会研究处理上传文件所需的逻辑。 - elton73

12

看起来有很多关于同一个问题的疑问 (Form::file: How to repopulate with Input::old After Validation Errors and/or on Update?),而所有明显具有相关知识的人都说这是不可能的。

我会提出一个解决办法,它涵盖了以下目标:

  • 在 Laravel 验证失败的情况下保留表单数据和文件输入
  • 只使用服务器端验证。你不需要绝不能使用 JavaScript 验证。

其中的关键词是AJAX。我会采取以下措施:

2017年12月更新:通过一个单个 AJAX POST发送所有字段和附加文件

  1. 创建一个 AJAX 表单(方法为GET POST),包含除了文件输入以外的一切内容。请记住,它需要发送Laravel CSRF 令牌
  2. 在控制器验证中,您需要使您的响应(失败或成功)生成 JSON 输出,这样您的 AJAX 发送代码可以在任何情况下获取响应,然后您可以在浏览器中显示它

这样,您就可以避免在服务器上出现任何临时状态的文件。

如果你担心使用带宽和预计输入字段有很多错误的情况下,你可以做一个更复杂但改进的版本,即进行两个(或更多)AJAX POST验证:第一个仅包含输入字段,如果一切正常,则再次发送所有字段(再次包括附加的文件)以尝试再次验证并在成功时执行所有数据操作。


5
如果您的文件是图像,您可以创建一个隐藏的输入框,在用户上传图像时将 base64 字符串写入其中。
{!! Form::open(array('url' => 'foo/bar')) !!}
{!! Form::text('image_name') !!}
{!! Form::hidden('base64_image') !!}
{!! Form::file('image') !!}
{!! Form::submit('Submit!') !!}
{!! Form::close() !!}

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