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

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

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

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

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

非常感谢


当前回答

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

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

其他回答

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

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

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

在这行之后删除zone.js:

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

大约在547行。

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

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);
});

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

Enyo的教程非常棒。

我发现教程中的示例脚本对于嵌入在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你还需要做一个清理脚本,检查上传目录的文件不使用,并删除他们。如果在前端未验证的形式:)

这是我的例子,是基于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>