Dropzone直接上传到nginx,我不想增加文件大小限制。活动存储确实具有直接上传功能,可以直接从客户端上传文件。但是我很困惑如何将其与dropzone一起使用,因为dropzone似乎以自己的方式上传文件,而direct_upload:true在这种情况下不起作用。
我的表单:
<%= form_for(@submission, html: { multipart: true, class: "dropzone", id: "file-upload"}) do |f| %>
<%= f.hidden_field :user_id %>
<%= f.hidden_field :problem_id %>
<% end %>
答案 0 :(得分:0)
我不确定您的设置是什么,但这是使用dropzone进行活动存储所需要的。
1)application.js
//= require dropzone
2)application.scss
*= require dropzone
// ...
.dropzone-target {
height: 100px;
width: 100px;
background-color: lightgrey;
}
3)dropzone_controller.js
// app/javascript/controllers/dropzone_controller.js
import {Controller} from "stimulus";
import {DirectUpload} from "activestorage";
export default class extends Controller {
uploadFile = (file, url, name) => {
const upload = new DirectUpload(file, url, this);
upload.create((error, blob) => {
if (error) {
// Handle the error
} else {
// Add an appropriately-named hidden input to the form with a
// value of blob.signed_id so that the blob ids will be
// transmitted in the normal upload flow
const hiddenField = document.createElement('input');
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("value", blob.signed_id);
hiddenField.name = name;
this.element.querySelector('form').appendChild(hiddenField);
}
});
};
connect() {
const root = this.element;
const fileInputField = root.querySelector('input[type="file"]');
const url = fileInputField.dataset.directUploadUrl;
const name = fileInputField.name;
fileInputField.remove();
this.myDropzone = new Dropzone(root.querySelector('.dropzone-target'), {
url,
autoQueue: false,
previewTemplate: '<div class="list-group-item w-100">\n' +
' <div class="row">' +
' <div class="col-2"><img data-dz-thumbnail class="img img-fluid" /></div>\n' +
' <div class="col-4">\n' +
' <span data-dz-size />\n' +
' </div><div class="col-6">\n' +
' <span data-dz-name></span>\n' +
' </div>\n' +
' </div><div class="row">\n' +
' <div class="col-12 mt-2"><div class="progress"><div class="progress-bar bg-dark" style="width:0%;" ></div></div></div>' +
' </div>\n' +
'</div>',
drop: (event) => {
event.preventDefault();
const files = event.dataTransfer.files;
Array.from(files).forEach(file => this.uploadFile(file, url, name))
}
});
}
disconnect() {
this.myDropzone = null;
}
directUploadWillStoreFileWithXHR(request) {
request.upload.addEventListener("progress",
event => this.directUploadDidProgress(event));
}
directUploadDidProgress(event) {
const root = this.element;
root.querySelector('.progress .progress-bar').style.width = `${event.loaded * 100 / event.total}%`;
}
}
4)edit.html.slim
div[data-controller="dropzone"]
= form_for @some_model do |f|
= f.file_field :file, direct_upload: true
.dropzone-target Drop files here
5)Gemfile
source 'https://rails-assets.org' do
gem 'rails-assets-dropzone'
end
6)package.json
{
"dependencies": {
"@rails/webpacker": "3.4",
"activestorage": "^5.2.1",
"stimulus": "^1.0.1",
},
"devDependencies": {
"webpack-dev-server": "2.11.2"
}
}