我目前有一个HTML表单,用户填写他们希望张贴的广告的细节。我现在想能够添加一个dropzone上传出售的项目的图像。
我发现Dropzone.js似乎做了我需要的大部分。但是,在查看文档时,似乎需要将整个表单的类指定为dropzone(而不仅仅是input元素)。这意味着我的整个表单变成了dropzone。
是否有可能使用dropzone只是我的形式的一部分,即只指定元素作为类“dropzone”,而不是整个形式?
我可以使用单独的表单,但我希望用户能够通过一个按钮提交所有内容。
或者,是否有其他库可以做到这一点?
非常感谢
我想在这里提供一个答案,因为我也面临着同样的问题-我们希望$_FILES元素作为另一个表单的一部分可用。我的答案是基于@mrtnmgs,但注意到这个问题的评论。
首先:Dropzone通过ajax发布数据
因为你使用了formData。附加选项仍然意味着你必须处理用户体验操作——也就是说,这一切都发生在幕后,而不是一个典型的表单post。数据被发送到url参数。
其次:如果您因此想要模拟表单发布,则需要存储发布的数据
这需要服务器端代码将你的$_POST或$_FILES存储在一个会话中,该会话可用于用户在另一个页面加载,因为用户不会转到收到发布数据的页面。
第三:您需要将用户重定向到处理该数据的页面
现在你已经发布了你的数据,存储在一个会话中,你需要在一个额外的页面中为用户显示/操作它。您还需要将用户发送到该页面。
举个例子:
[Dropzone code:使用Jquery]
$('#dropArea').dropzone({
url: base_url+'admin/saveProject',
maxFiles: 1,
uploadMultiple: false,
autoProcessQueue:false,
addRemoveLinks: true,
init: function(){
dzClosure = this;
$('#projectActionBtn').on('click',function(e) {
dzClosure.processQueue(); /* My button isn't a submit */
});
// My project only has 1 file hence not sendingmultiple
dzClosure.on('sending', function(data, xhr, formData) {
$('#add_user input[type="text"],#add_user textarea').each(function(){
formData.append($(this).attr('name'),$(this).val());
})
});
dzClosure.on('complete',function(){
window.location.href = base_url+'admin/saveProject';
})
},
});
更进一步,sqram说,Dropzone有一个额外的未记录的选项,“hiddenInputContainer”。您所要做的就是将此选项设置为您希望将隐藏文件字段附加到的表单的选择器。瞧!”。dz- hide -input”文件字段,Dropzone通常添加到主体神奇地移动到你的形式。没有改变Dropzone源代码。
现在,虽然这可以将Dropzone文件字段移动到表单中,但该字段没有名称。所以你需要添加:
_this.hiddenFileInput.setAttribute("name", "field_name[]");
在这行之后删除zone.js:
_this.hiddenFileInput = document.createElement("input");
大约在547行。
这是我的例子,是基于Django + Dropzone。视图有选择(必需的)和提交。
<form action="/share/upload/" class="dropzone" id="uploadDropzone">
{% csrf_token %}
<select id="warehouse" required>
<option value="">Select a warehouse</option>
{% for warehouse in warehouses %}
<option value={{forloop.counter0}}>{{warehouse.warehousename}}</option>
{% endfor %}
</select>
<button id="submit-upload btn" type="submit">upload</button>
</form>
<script src="{% static '/js/libs/dropzone/dropzone.js' %}"></script>
<script src="https://code.jquery.com/jquery-3.1.0.min.js"></script>
<script>
var filename = "";
Dropzone.options.uploadDropzone = {
paramName: "file", // The name that will be used to transfer the file,
maxFilesize: 250, // MB
autoProcessQueue: false,
accept: function(file, done) {
console.log(file.name);
filename = file.name;
done(); // !Very important
},
init: function() {
var myDropzone = this,
submitButton = document.querySelector("[type=submit]");
submitButton.addEventListener('click', function(e) {
var isValid = document.querySelector('#warehouse').reportValidity();
e.preventDefault();
e.stopPropagation();
if (isValid)
myDropzone.processQueue();
});
this.on('sendingmultiple', function(data, xhr, formData) {
formData.append("warehouse", jQuery("#warehouse option:selected").val());
});
}
};
</script>
我想在这里提供一个答案,因为我也面临着同样的问题-我们希望$_FILES元素作为另一个表单的一部分可用。我的答案是基于@mrtnmgs,但注意到这个问题的评论。
首先:Dropzone通过ajax发布数据
因为你使用了formData。附加选项仍然意味着你必须处理用户体验操作——也就是说,这一切都发生在幕后,而不是一个典型的表单post。数据被发送到url参数。
其次:如果您因此想要模拟表单发布,则需要存储发布的数据
这需要服务器端代码将你的$_POST或$_FILES存储在一个会话中,该会话可用于用户在另一个页面加载,因为用户不会转到收到发布数据的页面。
第三:您需要将用户重定向到处理该数据的页面
现在你已经发布了你的数据,存储在一个会话中,你需要在一个额外的页面中为用户显示/操作它。您还需要将用户发送到该页面。
举个例子:
[Dropzone code:使用Jquery]
$('#dropArea').dropzone({
url: base_url+'admin/saveProject',
maxFiles: 1,
uploadMultiple: false,
autoProcessQueue:false,
addRemoveLinks: true,
init: function(){
dzClosure = this;
$('#projectActionBtn').on('click',function(e) {
dzClosure.processQueue(); /* My button isn't a submit */
});
// My project only has 1 file hence not sendingmultiple
dzClosure.on('sending', function(data, xhr, formData) {
$('#add_user input[type="text"],#add_user textarea').each(function(){
formData.append($(this).attr('name'),$(this).val());
})
});
dzClosure.on('complete',function(){
window.location.href = base_url+'admin/saveProject';
})
},
});
我有一个更自动化的解决方案。
HTML:
<form role="form" enctype="multipart/form-data" action="{{ $url }}" method="{{ $method }}">
{{ csrf_field() }}
<!-- You can add extra form fields here -->
<input hidden id="file" name="file"/>
<!-- You can add extra form fields here -->
<div class="dropzone dropzone-file-area" id="fileUpload">
<div class="dz-default dz-message">
<h3 class="sbold">Drop files here to upload</h3>
<span>You can also click to open file browser</span>
</div>
</div>
<!-- You can add extra form fields here -->
<button type="submit">Submit</button>
</form>
JavaScript:
Dropzone.options.fileUpload = {
url: 'blackHole.php',
addRemoveLinks: true,
accept: function(file) {
let fileReader = new FileReader();
fileReader.readAsDataURL(file);
fileReader.onloadend = function() {
let content = fileReader.result;
$('#file').val(content);
file.previewElement.classList.add("dz-success");
}
file.previewElement.classList.add("dz-complete");
}
}
Laravel:
// Get file content
$file = base64_decode(request('file'));
没有必要禁用DropZone发现和正常的表单提交将能够通过标准表单序列化发送任何其他表单字段的文件。
该机制在处理文件时将文件内容存储为隐藏输入字段中的base64字符串。您可以通过标准的base64_decode()方法将其解码回PHP中的二进制字符串。
我不知道这种方法是否会受到大文件的影响,但它适用于~40MB的文件。