将Dropzone.js与其他字段集成到现有的HTML表单中

我目前有一个HTML表单,用户填写他们希望张贴的广告的细节。我现在希望能够添加一个dropzone用于上传待售物品的图像。

我已经找到Dropzone.js,这似乎做了大部分我需要的。然而,在查看文档时,似乎需要将整个表单的类指定为dropzone(而不仅仅是输入元素)。这意味着我的整个表单将变成dropzone

是否有可能使用dropzone只是我的形式的一部分,即仅指定元素为class "dropzone",而不是整个形式?

我可以使用单独的表单,但我希望用户能够通过一个按钮提交所有内容。

或者,是否有其他库可以做到这一点?

非常感谢

259991 次浏览

厄倪俄的教程是优秀的。

我发现教程中的示例脚本对于嵌入在dropzone中的按钮(即表单元素)工作得很好。如果你希望有窗体元素之外的按钮,我能够完成它使用一个点击事件:

首先,HTML:

<form id="my-awesome-dropzone" action="/upload" class="dropzone">
<div class="dropzone-previews"></div>
<div class="fallback"> <!-- this is the fallback if JS isn't working -->
<input name="file" type="file" multiple />
</div>


</form>
<button type="submit" id="submit-all" class="btn btn-primary btn-xs">Upload the file</button>

然后,脚本标记....

Dropzone.options.myAwesomeDropzone = { // The camelized version of the ID of the form element


// The configuration we've talked about above
autoProcessQueue: false,
uploadMultiple: true,
parallelUploads: 25,
maxFiles: 25,


// The setting up of the dropzone
init: function() {
var myDropzone = this;


// Here's the change from enyo's tutorial...


$("#submit-all").click(function (e) {
e.preventDefault();
e.stopPropagation();
myDropzone.processQueue();
});
}
}

这只是如何在现有表单中使用Dropzone.js的另一个例子。

dropzone.js:

 init: function() {


this.on("success", function(file, responseText) {
//alert("HELLO ?" + responseText);
mylittlefix(responseText);
});


return noop;
},

然后,在之后的文件里

function mylittlefix(responseText) {
$('#botofform').append('<input type="hidden" name="files[]" value="'+ responseText +'">');
}

这假设你有一个id为#botofform的div,这样在上传时你可以使用上传的文件名。

注意:我的上传脚本返回theuploadedfilename.jpeg Dubblenote你还需要做一个清理脚本,检查上传目录的文件不使用,并删除他们。如果在前端未验证的形式:)

这里有另一种方法:在你的表单中添加一个div类名为dropzone,并以编程方式实现dropzone。

HTML:

<div id="dZUpload" class="dropzone">
<div class="dz-default dz-message"></div>
</div>

JQuery:

$(document).ready(function () {
Dropzone.autoDiscover = false;
$("#dZUpload").dropzone({
url: "hn_SimpeFileUploader.ashx",
addRemoveLinks: true,
success: function (file, response) {
var imgName = response;
file.previewElement.classList.add("dz-success");
console.log("Successfully uploaded :" + imgName);
},
error: function (file, response) {
file.previewElement.classList.add("dz-error");
}
});
});

注意:禁用自动发现,否则Dropzone将尝试附加两次

你可以通过捕捉dropzone中的'sending'事件来修改formData。

dropZone.on('sending', function(data, xhr, formData){
formData.append('fieldname', 'value');
});
“dropzone.js”是最常用的上传图片的库。 如果你想让“dropzone.js”只是你表单的一部分,你应该执行以下步骤

1)对于客户端:

HTML:

    <form action="/" enctype="multipart/form-data" method="POST">
<input type="text" id ="Username" name ="Username" />
<div class="dropzone" id="my-dropzone" name="mainFileUploader">
<div class="fallback">
<input name="file" type="file" multiple />
</div>
</div>
</form>
<div>
<button type="submit" id="submit-all"> upload </button>
</div>

JQuery:

    <script>
Dropzone.options.myDropzone = {
url: "/Account/Create",
autoProcessQueue: false,
uploadMultiple: true,
parallelUploads: 100,
maxFiles: 100,
acceptedFiles: "image/*",


init: function () {


var submitButton = document.querySelector("#submit-all");
var wrapperThis = this;


submitButton.addEventListener("click", function () {
wrapperThis.processQueue();
});


this.on("addedfile", function (file) {


// Create the remove button
var removeButton = Dropzone.createElement("<button class='btn btn-lg dark'>Remove File</button>");


// Listen to the click event
removeButton.addEventListener("click", function (e) {
// Make sure the button click doesn't submit the form:
e.preventDefault();
e.stopPropagation();


// Remove the file preview.
wrapperThis.removeFile(file);
// If you want to the delete the file on the server as well,
// you can do the AJAX request here.
});


// Add the button to the file preview element.
file.previewElement.appendChild(removeButton);
});


this.on('sendingmultiple', function (data, xhr, formData) {
formData.append("Username", $("#Username").val());
});
}
};
</script>

2)服务器端:

ASP。Net MVC

    [HttpPost]
public ActionResult Create()
{
var postedUsername = Request.Form["Username"].ToString();
foreach (var imageFile in Request.Files)
{


}


return Json(new { status = true, Message = "Account created." });
}

更进一步,sqram说,Dropzone有一个额外的未记录的选项,“hiddenInputContainer”。您所要做的就是将此选项设置为您希望将隐藏文件字段附加到的表单的选择器。瞧!”。dz- hide -input”文件字段,Dropzone通常添加到主体神奇地移动到你的形式。没有改变Dropzone源代码。

现在,虽然这可以将Dropzone文件字段移动到表单中,但该字段没有名称。所以你需要添加:

_this.hiddenFileInput.setAttribute("name", "field_name[]");

在这行之后删除zone.js:

_this.hiddenFileInput = document.createElement("input");

大约在547行。

我遇到了完全相同的问题,发现瓦兰·西纳伊的答案是唯一真正解决了最初问题的答案。这个答案可以简化,所以这里有一个更简单的版本。

步骤如下:

  1. 创建一个标准的表单(不要忘记方法和enctype参数,因为这不再由dropzone处理)。

  2. 在里面放入一个带有class="dropzone"(这是Dropzone附加到它的方式)和id="yourDropzoneName"(用于更改选项)的div。

  3. 设置Dropzone的选项,设置表单和文件将被发布的url,取消激活autoProcessQueue(因此它只在用户按下“提交”时发生),并允许多次上传(如果你需要的话)。

  4. 当单击提交按钮时,将init函数设置为使用Dropzone而不是默认行为。

  5. 仍然在init函数中,使用“sendingmultiple”事件处理程序将表单数据与文件一起发送。

瞧!现在,您可以像使用普通表单一样在$_POST和$_FILES中检索数据(在本例中,这将发生在upload.php中)

超文本标记语言

<form action="upload.php" enctype="multipart/form-data" method="POST">
<input type="text" id ="firstname" name ="firstname" />
<input type="text" id ="lastname" name ="lastname" />
<div class="dropzone" id="myDropzone"></div>
<button type="submit" id="submit-all"> upload </button>
</form>

JS

Dropzone.options.myDropzone= {
url: 'upload.php',
autoProcessQueue: false,
uploadMultiple: true,
parallelUploads: 5,
maxFiles: 5,
maxFilesize: 1,
acceptedFiles: 'image/*',
addRemoveLinks: true,
init: function() {
dzClosure = this; // Makes sure that 'this' is understood inside the functions below.


// for Dropzone to process the queue (instead of default form behavior):
document.getElementById("submit-all").addEventListener("click", function(e) {
// Make sure that the form isn't actually being sent.
e.preventDefault();
e.stopPropagation();
dzClosure.processQueue();
});


//send all the form data along with the files:
this.on("sendingmultiple", function(data, xhr, formData) {
formData.append("firstname", jQuery("#firstname").val());
formData.append("lastname", jQuery("#lastname").val());
});
}
}

为了在一个请求中提交所有文件和其他表单数据,你可以复制Dropzone.js临时隐藏的input节点到你的表单中。你可以在addedfiles事件处理程序中这样做:

var myDropzone = new Dropzone("myDivSelector", { url: "#", autoProcessQueue: false });
myDropzone.on("addedfiles", () => {
// Input node with selected files. It will be removed from document shortly in order to
// give user ability to choose another set of files.
var usedInput = myDropzone.hiddenFileInput;
// Append it to form after stack become empty, because if you append it earlier
// it will be removed from its parent node by Dropzone.js.
setTimeout(() => {
// myForm - is form node that you want to submit.
myForm.appendChild(usedInput);
// Set some unique name in order to submit data.
usedInput.name = "foo";
}, 0);
});

显然,这是一种依赖于实现细节的变通方法。相关源代码

我有一个更自动化的解决方案。

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的文件。

这是我的例子,是基于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.append选项仍然意味着你必须处理UX操作——即这一切都发生在幕后,而不是一个典型的表单帖子。数据被传递给你的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';
})
},
});

5.7.0版本的工作解决方案

<form id="upload" enctype="multipart/form-data">
<input type="text" name="name" value="somename">
<input type="checkbox" name="terms_agreed">
<div id="previewsContainer" class="dropzone">
<div class="dz-default dz-message">
<button class="dz-button" type="button">
Drop files here to upload
</button>
</div>
</div>
<input id="dz-submit" type="submit" value="submit">
</form>
Dropzone.autoDiscover = false;
new Dropzone("#upload",{
clickable: ".dropzone",
url: "upload.php",
previewsContainer: "#previewsContainer",
uploadMultiple: true,
autoProcessQueue: false,
init() {
var myDropzone = this;
this.element.querySelector("[type=submit]").addEventListener("click", function(e){
e.preventDefault();
e.stopPropagation();
myDropzone.processQueue();
});
}
});


试试这个

<div class="dropzone dz-clickable" id="myDrop">
<div class="dz-default dz-message" data-dz-message="">
<span>Drop files here to upload</span>
</div>
</div>

JS

<script>
Dropzone.autoDiscover = false;
Dropzone.default.autoDiscover=false;
$("div#myDrop").dropzone({
url: "/file/post",
});
</script>