9

I'm trying to upload generated client side documents (images for the moment) with Dropzone.js.

// .../init.js

var myDropzone = new Dropzone("form.dropzone", {
    autoProcessQueue: true
}); 

Once the client have finished his job, he just have to click a save button which call the save function :

// .../save.js

function save(myDocument) {

    var file = { 
        name: 'Test',
        src: myDocument,
    };

    console.log(myDocument);

    myDropzone.addFile(file);
}

The console.log() correctly return me the content of my document

 data:image/png;base64,iVBORw0KGgoAAAANS...

At this point, we can see the progress bar uploading the document in the drop zone but the upload failed.

Here is my (standart dropzone) HTML form :

<form action="/upload" enctype="multipart/form-data" method="post" class="dropzone">
    <div class="dz-default dz-message"><span>Drop files here to upload</span></div>
    <div class="fallback">
        <input name="file" type="file" />
    </div>
</form>

I got a Symfony2 controller who receive the post request.

// Get request
$request = $this->get('request'); 

// Get files
$files = $request->files;

// Upload
$do = $service->upload($files);

Uploading from the dropzone (by drag and drop or click) is working and the uploads are successfull but using the myDropzone.addFile() function return me an empty object in my controller :

var_dump($files);

return

object(Symfony\Component\HttpFoundation\FileBag)#11 (1) {
  ["parameters":protected]=>
  array(0) {
  }
}

I think i don't setup correctly my var file in the save function. I tryied to create JS image (var img = new Image() ...) but without any success.

Thanks for your help !

ArGh
  • 1,148
  • 1
  • 11
  • 20
  • Take a look at this bundle: https://github.com/1up-lab/OneupUploaderBundle. It solves the problem you are having and many other you will probably have in the future. – Alberto Fernández Apr 01 '14 at 12:57
  • Sorry but no it don't. My dropzone is fonctionnal as my controller and action. It is the use of the addFile function which is not working because i work with an input containing the image source (creating dynamically in js) and i don't know how to transform it to be accepted by the addFile fonction. – ArGh Apr 01 '14 at 15:03

3 Answers3

17

Finally i found a working solution without creating canvas :

function dataURItoBlob(dataURI) {
    'use strict'
    var byteString, 
        mimestring 

    if(dataURI.split(',')[0].indexOf('base64') !== -1 ) {
        byteString = atob(dataURI.split(',')[1])
    } else {
        byteString = decodeURI(dataURI.split(',')[1])
    }

    mimestring = dataURI.split(',')[0].split(':')[1].split(';')[0]

    var content = new Array();
    for (var i = 0; i < byteString.length; i++) {
        content[i] = byteString.charCodeAt(i)
    }

    return new Blob([new Uint8Array(content)], {type: mimestring});
}

And the save function :

function save(dataURI) {

    var blob = dataURItoBlob(dataURI);
    myDropzone.addFile(blob);

}

The file appears correctly in dropzone and is successfully uploaded. I still have to work on the filename (my document is named "blob").

The dataURItoBlob function have been found here : Convert Data URI to File then append to FormData

[EDIT] : I finally wrote the function in dropzone to do this job. You can check it here : https://github.com/CasperArGh/dropzone And you can use it like this :

var dataURI = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAmAAAAKwCAYAAA...';
myDropzone.addBlob(dataURI, 'test.png');
Community
  • 1
  • 1
ArGh
  • 1,148
  • 1
  • 11
  • 20
3

I can't comment currently and wanted to send this to you.

I know you found your answer, but I had some trouble using your Git code and reshaped it a little for my needs, but I am about 100% positive this will work for EVERY possible need to add a file or a blob or anything and be able to apply a name to it.

Dropzone.prototype.addFileName = function(file, name) {
    file.name = name;
  file.upload = {
    progress: 0,
    total: file.size,
    bytesSent: 0
  };
  this.files.push(file);
  file.status = Dropzone.ADDED;
  this.emit("addedfile", file);
  this._enqueueThumbnail(file);
  return this.accept(file, (function(_this) {
    return function(error) {
      if (error) {
        file.accepted = false;
        _this._errorProcessing([file], error);
      } else {
        file.accepted = true;
        if (_this.options.autoQueue) {
          _this.enqueueFile(file);
        }
      }
      return _this._updateMaxFilesReachedClass();
    };
  })(this));
};

If this is added to dropzone.js (I did just below the line with Dropzone.prototype.addFile = function(file) { potentially line 1110.

Works like a charm and used just the same as any other. myDropzone.addFileName(file,name)!

Hopefully someone finds this useful and doesn't need to recreate it!

Cayce K
  • 2,288
  • 1
  • 22
  • 35
  • before anyone asks I have pasted blobs into it from screenshots (currently only on IE), but have not attempted to use it to upload other types of files. – Cayce K Aug 19 '14 at 15:05
0

1) You say that: "Once the client have finished his job, he just have to click a save button which call the save function:"

This implies that you set autoProcessQueue: false and intercept the button click, to execute the saveFile() function.

$("#submitButton").click(function(e) {
    // let the event not bubble up
    e.preventDefault();
    e.stopPropagation();
    // process the uploads
    myDropzone.processQueue();
});

2) check form action

Check that your form action="/upload" is routed correctly to your SF controller & action.

3) Example Code

You may find a full example over at the official Wiki

4) Ok, thanks to your comments, i understood the question better:

"How can i save my base64 image resource with dropzone?"

You need to embedd the image content as value

// base64 data
var dataURL = canvas.toDataURL();

// insert the data into the form
document.getElementById('image').value = canvas.toDataURL('image/png');
//or jQ: $('#img').val(canvas.toDataURL("image/png"));

// trigger submit of the form
document.forms["form1"].submit();
Community
  • 1
  • 1
Jens A. Koch
  • 39,862
  • 13
  • 113
  • 141
  • Thanks you for your response. 1) 2) – ArGh Apr 01 '14 at 14:49
  • 1) autoProcessQueue is currently "true". I have a unique dropzone which allow the user to drag and drop / click to upload but also an editor to create new images. I need autoProcessQueue to be "true" : creating a new image should push the created file into the queue which is immediatly uploaded if there is no more job. – ArGh Apr 01 '14 at 14:57
  • 2) As I said : Uploading from the dropzone (by drag and drop or click) is working and the uploads are successfull, so my route / controller / action are correctly configured . Only using the javascript function myDropzone.addFile() return me an empty object in my controller. – ArGh Apr 01 '14 at 14:58
  • 3) This example doesn't help me :). My main problem is what kind of object should I pass to the addFile() function as I have a string as image source – ArGh Apr 01 '14 at 15:00
  • addFile() accepts filenames https://github.com/enyo/dropzone/blob/master/lib/dropzone.js#L805 What you have is a image resource string. – Jens A. Koch Apr 01 '14 at 15:08
  • Is there a way to create a js object with my ressource string that dropzone can use ? – ArGh Apr 01 '14 at 17:52
  • Please see #4 in my comment. Use the base64 string and insert it in a hidden or image element in the DOM, then send the content. Its possibly easier with a pure AJAX send, then trying to push this into Dropzone. – Jens A. Koch Apr 01 '14 at 18:07
  • Thank you for your response, I will try to do like that. By the way, i find an issue asking for this behaviour : https://github.com/enyo/dropzone/issues/468 – ArGh Apr 03 '14 at 07:43
  • I changed the question title to be more explicit. Thank you very much for your help. – ArGh Apr 03 '14 at 09:03