Rails 4:如何使用 AJAX 上传文件
Posted
技术标签:
【中文标题】Rails 4:如何使用 AJAX 上传文件【英文标题】:Rails 4: How to upload files with AJAX 【发布时间】:2013-09-06 20:59:22 【问题描述】:我想用 AJAX 上传文件。在过去,我通过使用神奇的jQuery form plugin 来实现这一点,并且效果很好。目前我正在构建一个 Rails 应用程序并尝试以“Rails 方式”做事,所以我正在使用 Form Helper 和回形针 gem 添加文件附件。
rails docs 警告表单助手不适用于 AJAX 文件上传:
不同于其他表单制作一个异步文件上传表单不像 就像为 form_for 提供 remote: true 一样简单。使用 Ajax 表单 序列化由在浏览器中运行的 javascript 完成,并且 因为 JavaScript 不能从你的硬盘读取文件 无法上传。最常见的解决方法是使用不可见的 用作表单提交目标的 iframe。
似乎没有现成的解决方案。所以我想知道最聪明的做法是什么。好像我有几个选择:
-
使用表单助手和 iframe 技巧。
使用表单助手 + 加载 jQuery 表单插件来提交文件(不确定这是否会与 Rails 的真实性令牌等配合使用)
使用表单助手 + 回形针 + [其他一些 gem] 来扩展它的功能以允许提交 AJAX 表单。
这三个似乎都是可能的。我对#3知之甚少,特别是[其他一些宝石]部分。我发现了两个类似的问题(this 和this),其中提到了 Pic-Upload 的一个分支 Uploadify,但它们都有 2 年的历史并处理 Rails 2 和 3(并且 Uploadify 多年来没有更新)。所以考虑到发生了多少变化,我认为这确实是一个全新的问题:
在 Rails 4 中使用 AJAX 上传文件的最佳方式是什么?
【问题讨论】:
我认为这句话清楚地解释了为什么你总是“使用神奇的 jQuery 表单插件”;) 关于在 Rails 的表单助手旁边使用它的最流畅方式有什么建议吗?我在想我不应该使用 :remote=>true 而是让表单插件完成工作。 那个插件太棒了——刚刚试了一下,效果很好。感谢您提供信息丰富的问题:) 【参考方案1】:看看remotipart
gem:https://github.com/JangoSteve/remotipart -- 只需很少的工作就能让您一路走好!
【讨论】:
很多未解决的问题,我特别被那些关于 rails 4 兼容性的人吓坏了 我使用了带有 rails 4 的 remotipart,图像已上传,但响应 update.js.erb 没有被执行。 PLz帮助 仅供参考,这也适用于带有 Turbolinks 5 的 Rails 5。【参考方案2】:使用@rails/ujs。
查看(.html.erb):
<%= file_field_tag :file, id: "ajax_file_upload" %>
控制器(_controller.rb):
def update
@record = YourModel.find(params[:id])
respond_to do |format|
if @record.update_attributes(params[:your_model])
format.json render json: success: true
else
error_messages = @record.errors.messages.values.flatten
format.json render json: success: false, errors: error_messages
end
end
end
javascript(.js)
const uploadFile = element =>
const formData = new FormData();
formData.append("your_model[attribute_name]", element.target.files[0]);
Rails.ajax(
url: "your_model/:id",
type: "PUT",
beforeSend(xhr, options)
options.data = formData;
return true;
,
success: response =>
if (response.success)
alert("File uploaded successfully");
else
alert(response.errors.join("<br>"));
,
error: () =>
alert("ajax send error");
);
;
const documentOnReady = () =>
const fileField = document.getElementById("ajax_file_upload");
if (fileField)
fileField.addEventListener("change", uploadFile);
document.addEventListener("turbolinks:load", documentOnReady);
注意:使用FormData时不需要在ajax中设置RequestHeader。
FormData 使用与编码类型设置为“multipart/form-data”时表单相同的格式
【讨论】:
【参考方案3】:恕我直言,在使用 AJAX 处理上传文件时,Rails 并不完美,尤其是在您需要进度条的情况下。我的建议是使用 Javascript 通过 AJAX 请求提交表单,就像您在 (2) 中建议的那样。如果你熟悉 Javascript,你不会有很多问题。
我最近通过使用这个非常简单的 JS 库 https://github.com/hayageek/jquery-upload-file 使用了相同的方法,我在这里写了更多详细信息 http://www.alfredo.motta.name/upload-video-files-with-rails-paperclip-and-jquery-upload-file/
对于使用表单上传带有标题和描述的电影的应用程序,JS 代码如下所示:
$(document).ready(function()
var uploadObj = $("#movie_video").uploadFile(
url: "/movies",
multiple: false,
fileName: "movie[video]",
autoSubmit: false,
formData:
"movie[title]": $('#movie_title').text(),
"movie[description]": $('#movie_description').text()
,
onSuccess:function(files,data,xhr)
window.location.href = data.to;
);
$("#fileUpload").click(function(e)
e.preventDefault();
$.rails.disableFormElements($($.rails.formSubmitSelector));
uploadObj.startUpload();
);
);
远非完美,但为您的前端提供了灵活性。
【讨论】:
以上是关于Rails 4:如何使用 AJAX 上传文件的主要内容,如果未能解决你的问题,请参考以下文章
jQuery 表单插件 + Ajax 文件上传 + Rails