我花了几个小时试图解决这个问题。我在 Rails 中使用 Heroku 指南进行 S3 直接上传。我能够让它在我的定制版本中工作。在本地设置中效果很好,但在 Heroku 上效果不佳。我已将其缩小为 JS 问题,因为进度条不想加载。JS 使上传依赖于在开始上传之前的创建。我的 JS 技能很烂(我一直坚持下去,因为我必须这样做,但我非常讨厌 JS,这不适合我)。
应用程序.js:
//= require jquery
//= require jquery_ujs
//= require bootstrap
//= require jquery-table
//= require js/stellar
//= require js/nivo-lightbox.min
//= require js/custom
//= require js/css3-animate-it
//= require gritter
//= require turbolinks
//= require jquery-fileupload/basic
// = require_tree .
为了让它在测试中工作,我必须将脚本放在表单本身中。
_form.html.erb
<div class="row">
<div class="col-md-10 col-md-offset-1 text-center inner">
<%= form_for(@repair, html: { class: "directUpload", data: { 'form-data' => (@s3_direct_post.fields), 'url' => @s3_direct_post.url, 'host' => URI.parse(@s3_direct_post.url).host } }) do |f| %>
<% if @repair.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@repair.errors.count, "error") %> prohibited this repair from being saved:</h2>
<ul>
<% @repair.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field h3">
<%= current_user.email %>
</div>
<div class="field h3">
<%= f.label 'PPE Serial #' %>
<%= f.collection_select :ppe_id, current_user.ppes, :id, :serial %>
</div>
<div class="field h4">
<%= "Entered On: #{Date.today}" %><br />
</div>
<div class="field h4" id="photoUploader" >
<%= f.fields_for :photos, @repair.photos.build do |photos_fields| %>
<%= photos_fields.label :file_url, 'Upload a Photo' %>
<%= photos_fields.file_field :file_url %>
<% end %>
<div class='progress' id='pgbar'></div>
</div>
<div class="field h4">
<%= f.label :notes, 'Please give a detailed description of repairs needed.' %><br />
<%= f.text_area :notes, class: 'note_area' %>
</div>
<div class="actions">
<%= f.submit 'Save Record', class: 'btn btn-brand' %>
</div>
<script>
$(window).on('turbolinks:load', function() {
$('.directUpload').find("input:file").each(function(i, elem) {
var fileInput = $(elem);
var form = $(fileInput.parents('form:first'));
var submitButton = form.find('input[type="submit"]');
var progressBar = $("<div class='bar'></div>");
var barContainer = $("<div class='progress' id='pgbar'></div>").append(progressBar);
$('#pgbar').remove();
fileInput.after(barContainer);
fileInput.fileupload({
fileInput: fileInput,
url: form.data('url'),
type: 'POST',
autoUpload: true,
formData: form.data('form-data'),
paramName: 'file', // S3 does not like nested name fields i.e. name="user[avatar_url]"
dataType: 'XML', // S3 returns XML if success_action_status is set to 201
replaceFileInput: false,
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
progressBar.css('width', progress + '%')
},
start: function (e) {
submitButton.prop('disabled', true);
progressBar.
css('background', 'green').
css('display', 'block').
css('width', '0%').
text("Loading...");
},
done: function(e, data) {
submitButton.prop('disabled', false);
progressBar.text("Uploading done");
// extract key and generate URL from response
var key = $(data.jqXHR.responseXML).find("Key").text();
var url = '//' + form.data('host') + '/' + key;
// create hidden field
var input = $("<input />", { type:'hidden', name: fileInput.attr('name'), value: url })
form.append(input);
},
fail: function(e, data) {
submitButton.prop('disabled', false);
progressBar.
css("background", "red").
text("Failed");
}
});
});
});
</script>
<% end %>
</div>
</div>
我尝试在 application.js 文件中使用脚本,测试结果参差不齐,但在 Heroku 上不起作用。我也试过每一种组合
$(window).on('turbolinks:load', function() {
$(Document).on('turbolinks:load', function() {
$(document).ready(function(){
$(function(){
我已经预编译了资产,我已经禁用了这个表单的 turbolinks,禁用了这个页面的 turbo 链接,禁用了整个应用程序的 turbolinks,移动了 appplication.js 需要列表中的文件顺序。
我希望我能更好地理解 JS 来调整上传脚本,这样它就不会依赖于它似乎依赖于加载的内容。
我在 JS 控制台中没有收到任何错误。它只是加载或不取决于环境。
任何帮助深表感谢。
关于进度条的 JS 注释。在我的测试工作版本中,turbolinks 将继续为重新加载的栏创建容器 div。因此,正在创建空条,但它们根本不会干扰脚本。所以我创建了 div 然后添加了一个调用来删除它,这样如果它已经存在,它将在重新加载时被新的替换。