参数标识为字符串而不是文件
param identified as a string rather than a file
在我的视图文件 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
上使用参数
调用 post 请求
{"doc"=>"1.docx", "authenticity_token"=>"...."}
虽然我希望 doc
参数是我上传的文件 1.docx
,但 doc
参数仍然是文件 1.docx
的字符串 original_filename
].
我的 routes.rb
文件有代码
post "/winter" => "paper#submit"
而在 paper_controller 的提交方法中是代码:
File.write("Papers/rain.docx", params[:doc].read)
redirect_to "/paper"
相应地,当我提交上述表格时,我进入 /winters
url 并得到错误
undefined method 'read' for "1.docx":String
那么为什么 doc
参数设置为文件名而不是文件本身呢?这与文档相反,我想:[http://guides.rubyonrails.org/form_helpers.html#what-gets-uploaded]
还有一点,可能与此相关,是在文档的第一段中说:
Depending on the size of the uploaded file it may in fact be a StringIO or an instance of File backed by a temporary file.
那么,是不是说 params[:doc]
有时可能是一个文件实例,有时可能是一个字符串?如何处理这种随机行为?
还有一件事,如果我尝试 get
请求而不是 put
请求会怎么样? get
必须将参数放在 url 之后作为查询字符串,对吗?那么 params[:doc]
应该总是一个字符串吗?我尝试使用 get
,并被发送到 url
http://localhost:3000/winter?doc=1.docx
(当时我没有使用 authenticity token
参数的隐藏输入)。
当然,同样
undefined method 'read' for "1.docx":String
发生错误。
您必须使用 multipart/formdata encoding 才能进行文件传输。对于任何 Web 框架都是如此。
我建议您只使用表单助手,因为它会添加正确的真实性标记:
<%= form_tag("/winter", multipart: true) do %>
<%= file_field_tag 'doc' %>
# ...
<% end %>
And, one more thing, what if I tried get request instead of put
request? get has to put the params right after the url, as a query
string, right? So should then params[:doc] be always a string? I tried
using get, and was sent to the url
您不能在 GET 请求中上传文件。它们必须包含在使用 multipart/formdata 编码的 POST/PATCH/PUT 请求的请求正文中。
文件是二进制的 - 用于在 GET 请求中传递数据的查询字符串只是一个包含表单数据 key/value 对的字符串。因此,要在 GET 请求中传递文件,您需要对其进行 base64 编码,这会使文件大小增加约 30%。许多浏览器也像某些 Web 服务器一样限制 URI 的长度以防止 DOS 攻击,这使它成为一个非常糟糕的主意。
在我的视图文件 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 的提交方法中是代码:
File.write("Papers/rain.docx", params[:doc].read)
redirect_to "/paper"
相应地,当我提交上述表格时,我进入 /winters
url 并得到错误
undefined method 'read' for "1.docx":String
那么为什么 doc
参数设置为文件名而不是文件本身呢?这与文档相反,我想:[http://guides.rubyonrails.org/form_helpers.html#what-gets-uploaded]
还有一点,可能与此相关,是在文档的第一段中说:
Depending on the size of the uploaded file it may in fact be a StringIO or an instance of File backed by a temporary file.
那么,是不是说 params[:doc]
有时可能是一个文件实例,有时可能是一个字符串?如何处理这种随机行为?
还有一件事,如果我尝试 get
请求而不是 put
请求会怎么样? get
必须将参数放在 url 之后作为查询字符串,对吗?那么 params[:doc]
应该总是一个字符串吗?我尝试使用 get
,并被发送到 url
http://localhost:3000/winter?doc=1.docx
(当时我没有使用 authenticity token
参数的隐藏输入)。
当然,同样
undefined method 'read' for "1.docx":String
发生错误。
您必须使用 multipart/formdata encoding 才能进行文件传输。对于任何 Web 框架都是如此。
我建议您只使用表单助手,因为它会添加正确的真实性标记:
<%= form_tag("/winter", multipart: true) do %>
<%= file_field_tag 'doc' %>
# ...
<% end %>
And, one more thing, what if I tried get request instead of put request? get has to put the params right after the url, as a query string, right? So should then params[:doc] be always a string? I tried using get, and was sent to the url
您不能在 GET 请求中上传文件。它们必须包含在使用 multipart/formdata 编码的 POST/PATCH/PUT 请求的请求正文中。
文件是二进制的 - 用于在 GET 请求中传递数据的查询字符串只是一个包含表单数据 key/value 对的字符串。因此,要在 GET 请求中传递文件,您需要对其进行 base64 编码,这会使文件大小增加约 30%。许多浏览器也像某些 Web 服务器一样限制 URI 的长度以防止 DOS 攻击,这使它成为一个非常糟糕的主意。