在Dropzone中添加现有的图像文件

27

我正在使用 Dropzonejs 在表单中添加图像上传功能,由于表单中还有其他各种字段,因此我将 autoProcessQueue 设置为 false,并在单击提交按钮时处理表单,如下所示。

Dropzone.options.portfolioForm = { 

    url: "/user/portfolio/save",
    previewsContainer: ".dropzone-previews",
    uploadMultiple: true,
    parallelUploads: 8,
    autoProcessQueue: false,
    autoDiscover: false,
    addRemoveLinks: true,
    maxFiles: 8,

    init: function() {

         var myDropzone = this;
         this.element.querySelector("button[type=submit]").addEventListener("click", function(e) {

             e.preventDefault();
             e.stopPropagation();
             myDropzone.processQueue();
         });
     }
 }

这个方法很好,可以在表单提交时处理所有发送的图像。但是,我还想能够在用户再次编辑表单时查看用户已经上传的图像。所以我查阅了来自Dropzone Wiki的以下帖子。

https://github.com/enyo/dropzone/wiki/FAQ#how-to-show-files-already-stored-on-server

该帖子使用现有图像填充 dropzone-preview 区域,但这次不会随表单提交发送现有图像。我想这是因为这些图像没有添加到queue中,但如果是这样,那么如何在服务器端进行更新呢?万一用户删除了现有的图像,怎么办?

此外,哪种方法更好:将已添加的图像再次添加到queue中,还是只发送已删除文件的信息?

8个回答

32

我花了一些时间尝试再次添加图片,但是在与它斗争了一段时间后,最终我只是将有关已删除图片的信息发送回服务器。

当使用现有图片填充dropzone时,我会将图片的URL附加到mockFile对象上。在removedfile事件中,如果正在删除的文件是预填充图片(通过测试传入事件的文件是否具有url属性确定),则向表单添加隐藏输入。下面是相关代码:

Dropzone.options.imageDropzone = {
    paramName: 'NewImages',
    autoProcessQueue: false,
    uploadMultiple: true,
    parallelUploads: 100,
    maxFiles: 100,
    init: function () {
        var myDropzone = this;

        //Populate any existing thumbnails
        if (thumbnailUrls) {
            for (var i = 0; i < thumbnailUrls.length; i++) {
                var mockFile = { 
                    name: "myimage.jpg", 
                    size: 12345, 
                    type: 'image/jpeg', 
                    status: Dropzone.ADDED, 
                    url: thumbnailUrls[i] 
                };

                // Call the default addedfile event handler
                myDropzone.emit("addedfile", mockFile);

                // And optionally show the thumbnail of the file:
                myDropzone.emit("thumbnail", mockFile, thumbnailUrls[i]);

                myDropzone.files.push(mockFile);
            }
        }

        this.on("removedfile", function (file) {
            // Only files that have been programmatically added should
            // have a url property.
            if (file.url && file.url.trim().length > 0) {
                $("<input type='hidden'>").attr({
                    id: 'DeletedImageUrls',
                    name: 'DeletedImageUrls'
                }).val(file.url).appendTo('#image-form');
            }
        });
    }
});

服务器代码 (asp mvc 控制器):

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(ViewModel viewModel)
{
    if (ModelState.IsValid)
    {
        foreach (var url in viewModel.DeletedImageUrls)
        {
            // Code to remove the image
        }

        foreach (var image in viewModel.NewImages)
        {
            // Code to add the image
        }
    }
}

我希望这能有所帮助。


谢谢Teppic,是的我也不得不这么做。 :) - lalit
2
一个小改进:在mockFile中添加“accepted: true”,这样Dropzone就可以将文件识别为已正确上传。例如,这使得可上传文件的限制(“maxFiles”)生效。 - user1825294
非常好,运行得很顺利。 - mdev
太棒了!感谢这个。 - John Dorian
如果使用 accepted: true,你还需要执行 myDropzone.emit("complete", mockFile); 来确保文件被成功上传,否则它将会显示上传进度条,这可能会让一些人感到困惑! - Anupam
显示剩余2条评论

17

在 Teppic 的回答基础上,我发现你需要触发完整的事件才能在预览中移除进度条。

var file = {
    name: value.name,
    size: value.size,
    status: Dropzone.ADDED,
    accepted: true
};
myDropzone.emit("addedfile", file);                                
myDropzone.emit("thumbnail", file, value.path);
myDropzone.emit("complete", file);
myDropzone.files.push(file);

1
状态和已接受是很重要的,如果我们不加上它,maxFiles 将会出错。 - Sruit A.Suk

3
这方面有官方的常见问题解答,可以在这里查看。

1
我确认在2020年8月使用Dropzone 5.7.2时这个功能是可用的。 - Jasom Dotnet

3

这个函数应该传递什么样的数据? - Oleg Shakhov
当我尝试使用addFile()时,出现错误“无法读取未定义的属性'replace'”。我需要以特殊方式组合文件对象吗?我使用的是Dropzone ver 5.5。 - Der Wolf
你可以传递一个JavaScript文件或Dropzone文件,参见: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/dropzone/index.d.ts#L182 和 https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/dropzone/index.d.ts#L29 另外,请参阅: https://developer.mozilla.org/en-US/docs/Web/API/File/Using_files_from_web_applications - Fareed Alnamrouti

2
我使用dropzone内置的"displayExistingFile"方法解决了这个问题。
在您的init:function中,
1.创建模拟文件 let mockFile = {name:file.title,size:file.size,dataURL:};
2.调用displayExistingFile函数
this.displayExistingFile(mockFile,null,null,'anonymous');
您可以将'null'替换为回调函数以响应缩略图加载事件。
'anonymous'是跨域属性。

1
我的 dropzone.js 版本(v5.5)中找不到 displayExistingFile 函数。 - Der Wolf

1

最初我是为了以编程方式上传现有文件而这样做的:

myDropzone.emit("addedfile", imageFile);                                
myDropzone.emit("thumbnail", imageFile, imageUrl);
myDropzone.files.push(file);

然而,参考Dropzone Github Issue,我发现了一种更简单的直接上传方式:

myDropzone.uploadFiles([imageFile])

很不幸,Dropzone文档中没有关于uploadFiles方法的参考资料,因此我想与所有Dropzone用户分享一些知识。
希望这能帮助到某些人。

1
你的代码的第一部分是模拟上传过程,实际上并未将任何东西发布到服务器上。而 myDropzone.uploadFiles([imageFile]) 则是向服务器发布内容,所以它们是不同的。 - Mohamed Mo Kawsara

1
如果您有文件的URL,您可以使用addFile添加该文件。
fetch("url")
    .then(res => res.blob())
    .then((currentBlob) => {
        const generateFile = new File([currentBlob], "filename.jpg", {
            type: currentBlob.type,
        });
        myDropzone.addFile(generateFile);
    });

0
点击上传文件时,只需清除放置区中的文件。 可以使用removeAllFiles()来清除所有文件,或者通过使用removeFile(fileName)来删除特定文件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接