Programmatically Add Existing File to Dropzone
Asked Answered
F

12

27

I'm trying to add an existing image to my dropzone programmatically, using the dropzone.js FAQ as a guide:

// Add the existing image if it's there.
// headerDropzone is my dropzone (debug shows it as existing and initialized at this point.
var on_load_header = $( '[name="on_load_header_image"]' ).val();
var on_load_header_path = $( '[name="on_load_header_image_path"]' ).val();

if ( on_load_header ) {

    // Hardcoded size value is just for testing, see my second question below.
    var on_load_header_data = { name: on_load_header, size: 12345 };

    // Call the default addedfile event handler
    headerDropzone.options.addedfile.call( headerDropzone, on_load_header_data );

    // And optionally show the thumbnail of the file:
    headerDropzone.options. thumbnail.call( headerDropzone, on_load_header_data, on_load_header_path);

}

My first problem is that this is just not working. The addedfile event doesn't fire (or at least the addedfile handler in headerDropzone never fires), same goes for thumbnail.

My second problem/question is: do I have to provide the file size? I could get it server side, but I'd rather not do it if I don't actually need to.

Failsafe answered 10/7, 2013 at 23:35 Comment(0)
E
11

See if the functions headerDropzone.options.addedfile and headerDropzone.options.thumbnail are actually defined. It should work the way you did it, but without further info it's difficult to tell what's wrong.

About the filesize: No, it's not necessary to actually provide the accurate filesize. It's just that Dropzone automatically displays the filesize. If you don't care if some false filesize is displayed then you can just provide some random number or 0. Otherwise you might want to hide the filesize with CSS, or with JS after you add it. (The element in question has the class dz-size.

The JavaScript version of it would look something like this:

var fileSizeElement = on_load_header_data.previewElement.querySelector(".dz-size");
fileSizeElement.parentNode.removeChild(fileSizeElement);
Edda answered 11/7, 2013 at 21:15 Comment(2)
Thanks so much for your answer. I went with a different approach that was a better fit for my particular application. Thanks for dropzone, btw, it's a pleasure to work with.Failsafe
Note, code as changed in dropzone and we need to replace myDropzone.options.addedFile.call(myDropzone, mockFile) for myDropzone.emit("addedfile", mockFile). See example in the updated faqBrittaney
W
29

If you need to add multiple existing files into Dropzone, declare your existing files as array and then add it into Dropzone programmatically inside a loop like so...

        Dropzone.autoDiscover = false;
        var myDropzone = new Dropzone("#myDropzone", {
            url: "/file/post",
            maxFileSize: 50,
            acceptedFiles: ".pdf",
            addRemoveLinks: true,
            //more dropzone options here
        });

        //Add existing files into dropzone
        var existingFiles = [
            { name: "Filename 1.pdf", size: 12345678 },
            { name: "Filename 2.pdf", size: 12345678 },
            { name: "Filename 3.pdf", size: 12345678 },
            { name: "Filename 4.pdf", size: 12345678 },
            { name: "Filename 5.pdf", size: 12345678 }
        ];

        for (i = 0; i < existingFiles.length; i++) {
            myDropzone.emit("addedfile", existingFiles[i]);
            //myDropzone.emit("thumbnail", existingFiles[i], "/image/url");
            myDropzone.emit("complete", existingFiles[i]);                
        }
Wray answered 22/2, 2015 at 14:1 Comment(3)
Thanks, this helped me added existing files to my drop zones.Dragrope
is there any way to remove those files, which i had added programatically ??Interlard
@MayankMajithya, Refer to this line addRemoveLinks: true,. And please post a new question if you need further clarification.Wray
D
25

The Dropzone FAQ leaves out important settings required to properly preload a dropzone with (an) existing file(s).

My init method for my dropzone:

Dropzone.options.MyDropZoneID = {
    ...
    init: function () {
        var mockFile = { name: fileName, size: fileSize, type: fileMimeType, serverID: 0, accepted: true }; // use actual id server uses to identify the file (e.g. DB unique identifier)
        this.emit("addedfile", mockFile);
        this.createThumbnailFromUrl(mockFile, fileUrl);
        this.emit("success", mockFile);
        this.emit("complete", mockFile);
        this.files.push(mockFile);
        ...

I don't know if the above is a perfect implementation, but it is working correctly with the maxFiles setting. Which is very important if you don't want buggy behavior (like the default message displaying when it shouldn't or extra files getting uploaded). You definitely need to set the accepted property to true and add the file to the files property. The only thing that I think is not required is emitting the success. I haven't played around with that enough though to know for sure.

Note: I used the following NuGet package:

  • Created by: Matias Meno
  • Id: dropzone
  • Version: 4.2.0
Dragrope answered 6/11, 2015 at 16:8 Comment(1)
This work perfectly for me in version 5.9. To set "accepted" to "true" was very important in my case, because only than the maxfilesexceeded actually triggers. Tanks!Brazier
E
11

See if the functions headerDropzone.options.addedfile and headerDropzone.options.thumbnail are actually defined. It should work the way you did it, but without further info it's difficult to tell what's wrong.

About the filesize: No, it's not necessary to actually provide the accurate filesize. It's just that Dropzone automatically displays the filesize. If you don't care if some false filesize is displayed then you can just provide some random number or 0. Otherwise you might want to hide the filesize with CSS, or with JS after you add it. (The element in question has the class dz-size.

The JavaScript version of it would look something like this:

var fileSizeElement = on_load_header_data.previewElement.querySelector(".dz-size");
fileSizeElement.parentNode.removeChild(fileSizeElement);
Edda answered 11/7, 2013 at 21:15 Comment(2)
Thanks so much for your answer. I went with a different approach that was a better fit for my particular application. Thanks for dropzone, btw, it's a pleasure to work with.Failsafe
Note, code as changed in dropzone and we need to replace myDropzone.options.addedFile.call(myDropzone, mockFile) for myDropzone.emit("addedfile", mockFile). See example in the updated faqBrittaney
H
9

This is now answered in official FAQ

Dropzone.options.myDropzone = {
  init: function() {
    let myDropzone = this;

    // If you only have access to the original image sizes on your server,
    // and want to resize them in the browser:
    let mockFile = { name: "Filename 2", size: 12345 };
    myDropzone.displayExistingFile(mockFile, "https://i.picsum.photos/id/959/600/600.jpg");

    // If the thumbnail is already in the right size on your server:
    let mockFile = { name: "Filename", size: 12345 };
    let callback = null; // Optional callback when it's done
    let crossOrigin = null; // Added to the `img` tag for crossOrigin handling
    let resizeThumbnail = false; // Tells Dropzone whether it should resize the image first
    myDropzone.displayExistingFile(mockFile, "https://i.picsum.photos        /id/959/120/120.jpg", callback, crossOrigin, resizeThumbnail);
    myDropzone.files.push(mockFile); // line missing in official docs

    // If you use the maxFiles option, make sure you adjust it to the
    // correct amount:
    let fileCountOnServer = 2; // The number of files already uploaded
    myDropzone.options.maxFiles = myDropzone.options.maxFiles - fileCountOnServer;
  }
};
Harl answered 23/6, 2017 at 10:7 Comment(0)
L
7

Originally I was doing something along these lines to programmatically upload a pre-existing file to Dropzone:

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

However, referencing this Dropzone Github Issue I found an easier way to directly upload:

headerDropzone.uploadFiles([imageFile])

Unfortunately there are no references to this uploadFiles method in the Dropzone Documentation, so I figured I'd share some knowledge with all you Dropzone users.

Hope this helps someone

Lu answered 22/4, 2016 at 19:49 Comment(2)
When I try to use uploadFiles([file]) with chunking I get an error: "Uncaught TypeError: Cannot read property 'chunked' of undefined"Iberian
Same with me @Lokiare. any update on this @Cumulo.?Hesson
C
4

I had the same problem and found Dropzone's handleFiles(files) method.

So if you have inputTypeFileRef, you can

// inputTypeFiles.files is an object of type FileList
var fileArray = Object.values(inputTypeFiles.files || {});
myDropZone.handleFiles(fileArray);

That will also trigger all the Dropzone's events and pass file(s) data that it normally would by dragging a file on it - progress, file size, etc.

Hope it helped.

Coup answered 5/5, 2016 at 15:50 Comment(1)
This one works with the new chunked upload feature. Although you can just use myDropZone.handleFiles([file]);Iberian
M
3

The latest Dropzone is lack of examples and the documentation is not clear or incomplete. You can use the following to add existing images to Dropzone.

for (var i = 0; i < imagesList.length; i++) {
  let name = imagesList[i];
  name = name.substring(name.lastIndexOf('/') + 1);

  fetch(imagesList[i])
    .then(res => res.blob())
    .then(blob => {
      let file = new File([blob], name, blob);
      myDropzone1.addFile(file);
    });
}

imagesList is a list of images which you want to add to Dropzone.

However, I am still facing a problem: Images are not being added or shown in the order/sequence as in imagesList. They appear rather random. Is there a way to make the images shown in the order/sequence as in imagesList?

Mood answered 26/12, 2018 at 9:44 Comment(2)
This answer makes a lot of sense. Note that Dropzone accepts loading blob directly without creating a file object: blob.name = name; myDropzone1.addFile(blob);. Not sure regarding the order of list.Greenhaw
.addFile() still appears to work as of this comment. By far the easiest way, compared to all the other answers here.Gunstock
E
1

Many of these answers are pretty dated, this is working for me in the latest Dropzone JS at the time of writing (take note of the included comments):

init: function() {
    var dzObj = this;

    // In my template I looped through existing files from the database and created:
    // <div class="existing-image" data-url="/path/to/file.jpg"></div>
    $('.existing-image').each(function() {
        // I didn't have this data - works fine without
        var mockFile = { name: '', size: '', dataURL: $(this).data('url') };

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

        // The Dropzone JS FAQ incorrectly references "file" here instead of  mockFile".
        // The other parameters are outdated, dataURL goes in the object above,
        // and you need to pass through other parameters.
        // It DOES NOT WORK without the thumbnail event being triggered.
        dzObj.createThumbnailFromUrl(mockFile, dzObj.options.thumbnailWidth, dzObj.options.thumbnailHeight, dzObj.options.thumbnailMethod, true, function (dataUrl) {
            dzObj.emit("thumbnail", mockFile, dataUrl);
        });

        // Make sure that there is no progress bar, etc...
        dzObj.emit("complete", mockFile);

        dzObj.options.maxFiles = dzObj.options.maxFiles - 1;
    });
}
Encounter answered 5/2, 2019 at 14:13 Comment(2)
Using this code, I have managed to add existing images to dropzone. But, when I want to resubmit the form (with the dropzone images), the images are not recognized (dzObj.getUploadingFiles().length === 0 && dzObj.getQueuedFiles().length === 0) and so it didn't work. Any solution to this problem? Thanks.Mood
This is the only example that works with latest version. Internet is full of incorrect answers.. Accepted answer should be updated to this. Also dropzone.js what is this nightmare of adding an image? Expecting addImage() function...Lioness
P
0

@tjbp's response worked well for me, with the following changes:

  1. I could not delete the programatically added file and then add another. I fixed this by removing this line, which was setting "maxFiles" to 0.

    // If you use the maxFiles option, make sure you adjust it to the
    // correct amount:
    var existingFileCount = 1; // The number of files already uploaded
    myDropzone.options.maxFiles = myDropzone.options.maxFiles - existingFileCount;
    
  2. To make sure the "Delete" button was visible, I had to add the following line:

    if (mockFile.previewElement) {
        mockFile.previewElement.classList.add("dz-success");
    }
    
Phocaea answered 28/9, 2019 at 2:8 Comment(0)
I
0

Nothing here worked for me with version 5.7.0 but this did:

var myDropzone = new Dropzone(document.body, {
    url: "<?= site_url('site/upload') ?>",
    acceptedFiles: "<?= $uploadFieldAcceptValue ?>",
    maxFilesize: 15,
    maxFiles: 5,
    autoQueue: false,
    thumbnailWidth: 80,
    thumbnailHeight: 80,
    init: function(){
        var that = this;

        that.on("addedfile", function(file) {
            // remove the start button
            var startButton = file.previewElement.querySelector(".start");
            if(startButton){
                startButton.parentNode.removeChild(startButton);
            }
        });

        <?php if(is_array($userUploads) && count($userUploads) > 0) { ?>
            <?php foreach($userUploads as $userUpload) { ?>
                <?php $file = $userUpload['file']; ?>

                var mockFile = {
                    name: '<?= basename($file) ?>', 
                    size: <?= filesize($file) ?>
                };

                var fileUrl = '<?= base_url() . str_replace('\\', '/', preg_replace('~^'. preg_quote(FCPATH) .'~', '', $file)) ?>';
                var callback = null;
                var crossOrigin = null;
                var resizeThumbnail = true;
                that.displayExistingFile(mockFile, fileUrl, callback, crossOrigin, resizeThumbnail);

                that.emit("success", mockFile);
                that.emit('complete', mockFile);

            <?php } ?>

            that.options.maxFiles = that.options.maxFiles - <?= count($userUploads) ?>;

        <?php } ?>
    }
});
Imperceptive answered 17/3, 2020 at 21:9 Comment(1)
gitlab.com/meno/dropzone/-/wikis/…Imperceptive
L
0

On Dropzone 5.7.0 there is a "displayExistingFile" function. I called it on init section, works fine.

     /**
     * Called when dropzone initialized
     * You can add event listeners here
     */
    init: function init() {
      var mockFile = { name: "Filename 1.pdf", size: 12345678 }; 
      this.displayExistingFile(mockFile,  "../../assets/site/wp-content/uploads/cropped-ic_credifisco-1-192x192.png");     
    },
Lauranlaurance answered 10/4, 2020 at 10:14 Comment(0)
R
0

While displayExistingFile() method worked for me and showed the file, my use case was slightly different. Each time I submit my form, it purges old attachments and saves only the new ones, so I needed Dropzone to also actually load these old images. That also made it easier to handle deleting images as callbacks simply work on default remove links. Here is how I got this to work.

// existing images in my case come from an array generated by backend and assigned to a data attribute, but for simplicity and demonstration purposes, I just made it a variable here
const existingImages = [
  {
    url: "https://actual_url_on_the_server.jpg",
    filename: "existing_file_1.jpg",
  }
  ...
];

async fetchExistingFiles() {
  // Generates a map where "key" is filename and "value" is a generated blob.
  // Done this way, as fetch/Promise.all() don't keep the responses in the same order as they were requested
  // This way, I can later on loop through existing images array passed from backend that is in the correct order, find a blob by filename (the key)
  // and display existing imagery in the correct order that matches the backend
  const blobsMap = new Map();
  const promises = existingImages.map(async ({ filename, url }) => {
    await fetch(url)
      .then((response) => response.blob())
      .then((existingImageBlob) => blobsMap.set(filename, existingImageBlob));
  });

  await Promise.all(promises);

  return blobsMap;
}

async displayExistingFiles() {
  const existingFilesBlobsMap = await fetchExistingFiles();

  // Display responses in the same order as backend using the Map generated above
  // and choosing items by filename (key)
  existingImages.forEach(({ filename }) => {
    const existingBlobData = existingFilesBlobsMap.get(filename);
    const tempFile = new File([existingBlobData], filename, existingBlobData);
    dropzone.addFile(tempFile); // used on actual Dropzone instance
  });
}

// run this on page load (or whenever you need)
displayExistingFiles();
Religiosity answered 25/10, 2023 at 6:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.