【问题标题】:param identified as a string rather than a file参数标识为字符串而不是文件
【发布时间】:2018-05-08 07:51:15
【问题描述】:

在我的视图文件submit.html.erb 中,我决定直接使用<form> 标签,而不是rails 中包含的表单助手。这是视图文件:

<form action = "/winter" method="post">
<input type="file" name="doc">
<p> Upload your question. </p>
<input type = "submit">
 <input name="authenticity_token" type="hidden" 
      value="....">
</form>

提交此表单会在 /winters 上调用带有参数的发布请求

{"doc"=>"1.docx", "authenticity_token"=>"...."}

虽然我预计doc 参数是我上传的文件1.docx,但doc 参数仍然是文件1.docx 的字符串original_filename

我的routes.rb 文件有代码

post "/winter" => "paper#submit"

而在paper_controller的submit方法里面是代码:

File.write("Papers/rain.docx", params[:doc].read)
redirect_to "/paper"

相应地,当我提交上述表单时,我转到/winters url 并得到错误

“1.docx”的未定义方法“读取”:字符串

那么为什么doc 参数设置为文件名而不是文件本身呢?这与文档相反,我想:[http://guides.rubyonrails.org/form_helpers.html#what-gets-uploaded]

还有一点,可能与此处相关,是在文档的第一段中它说:

根据上传文件的大小,它实际上可能是 StringIO 或由临时文件支持的 File 实例。

那么,是不是说有时params[:doc] 可能是一个文件实例,有时它可能是一个字符串?如何处理这种随机行为?

还有一件事,如果我尝试get 请求而不是put 请求呢? get 必须将参数放在 url 之后,作为查询字符串,对吗?那么params[:doc] 应该始终是一个字符串吗?我尝试使用get,并被发送到url

http://localhost:3000/winter?doc=1.docx

(那时我没有使用 authenticity token 参数的隐藏输入)。 当然也一样

“1.docx”的未定义方法“读取”:字符串

发生错误。

【问题讨论】:

    标签: ruby-on-rails forms file-io http-method


    【解决方案1】:

    您必须使用multipart/formdata encoding 才能进行文件传输。这适用于任何 Web 框架。

    我建议您只使用表单助手,因为它会添加正确的真实性令牌:

    <%= form_tag("/winter", multipart: true) do %>
      <%= file_field_tag 'doc' %>
      # ...
    <% end %>
    

    还有一件事,如果我尝试 get request 而不是 put 要求? get 必须将参数放在 url 之后,作为查询 字符串,对吧?那么 params[:doc] 应该始终是一个字符串吗?我试过了 使用get,并被发送到url

    您不能在 GET 请求中上传文件。它们必须包含在使用 multipart/formdata 编码的 POST/PATCH/PUT 请求的请求正文中。

    文件是二进制的——用于在 GET 请求中传递数据的查询字符串只是一个包含表单数据键/值对的字符串。因此,要在 GET 请求中传递文件,您需要对其进行 base64 编码,这会使文件大小膨胀约 30%。许多浏览器还限制 URI 的长度,一些 Web 服务器也这样做,以防止 DOS 攻击,这使得它成为一个非常糟糕的主意。

    【讨论】:

    • [w3schools.com/tags/att_form_enctype.asp] 表示“只有在 method="post" 和 application/x-www-form-urlencodedenctype 属性的默认值时才能使用 enctype 属性。所以每当我使用输入type="file"必须 使用enctype=multipart/form-data,对吗?但是 w3schools 中的文件上传示例几乎从未在文件上传示例中使用enctype。那么为什么他们没有包含强制性的enctype=multipart/form-data 行,如果没有它,服务器端处理就会崩溃?我的意思是,服务器需要一个正确的文件,而不是文件名字符串。
    • 如前所述,W3Schools 是点击诱饵垃圾,不幸的是在谷歌上排名很高。如果您需要正确的参考,请使用MDN
    猜你喜欢
    • 1970-01-01
    • 2013-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-24
    • 2023-01-23
    • 2011-07-24
    相关资源
    最近更新 更多