2

I have an Angular application where I am using the drag-and-drop file upload component, Dropzone.js. The uploaded file will be posted directly to an Azure blob. Azure requires me to generate a unique URL for each file upload.

Dropzone.js has a config option called "url" that can be a string or a function. I need to call my angular service from this function to generate the Azure signed URL where the file will be sent. In my controller, I generate the config for Dropzone as:

var options = {
                url: function (files) {
                    var f = files[0];
                    return _fileHandlingService.getUploadUrl(f.name);
                },
                maxFiles: 10,
                maxFilesize: 20,
                acceptedFiles: "image/*",
                method: "PUT"
            };

My file handling service is as follows:

getUploadUrl = function (filename) {
            this.$http.get("/api/getUploadUrl", { params: { filename: filename } }).then(function (resp) {
                return resp.data;
            });
        };

The problem is that the promise doesn't resolve in time for it to be provided to Dropzone and Dropzone doesn't support promises. How should this be handled assuming we don't rewrite Dropzone to support promises? I have been able to find a way to make everyting stop until the promise is resolved.

5
  • No, the problem is that your are assigning a promise to the url property which I'm guessing DropZone won't wait for. You should just wrap the entire options creation and whatever other calls you need to make in the promise resolution callback, ie _fileHandlingService.getUploadUrl(f.name).then(function(url) { var options = ... Commented Apr 29, 2015 at 2:22
  • I can't really do this because of how Dropzone works. The options object is passed during the initial configuration of the plugin. The url function is not called until files are dragged into the plugin to be uploaded. With the parameters I have set, the url function gets called once for each file uploaded and I need to use this filename to get the Azure blob URL. Commented Apr 29, 2015 at 2:24
  • 1
    I haven't tried this so I don't have the all details but... you might first disable automatic processing, then use dropzone's .getAcceptedFiles() to grab all the files. Next run your service to get urls and store them in an array. Finally, call .processQueue(). The option url function processes your file array -- That won't get called (I think) until you actually start processing the queue. Unfortunately, with this method you'll have to press a button to start actual uploading. Commented Apr 29, 2015 at 3:01
  • 1
    Thinking about this more, you could wait for the service promise to trigger .processQueue() so it will be "automatic" to the user. Commented Apr 29, 2015 at 3:06
  • Jasen, you sent me down the right path. I've been able to do with using the accept call back. I will post a full answer. Commented Apr 29, 2015 at 5:05

1 Answer 1

2

Dropzone has a callback named "accept". One of the parameters is a function that gets called if everything is successful. As a result, we can call this done function when our promise returns. One downside to this method is that the URLs are generated when the files are queued vs uploaded. In my case, there is a small chance that the URL could expire depending on my expiration date and how long it takes the user to upload. My config options now look like:

var options = {
                url: function (files) {
                    var f = files[0];
                    return f.uploadUrl;
                },
                maxFiles: 10,
                maxFilesize: 20,
                acceptedFiles: "image/*",
                method: "PUT",
                accept: function (file, done) {
                    _fileHandlingService.getUploadUrl(file.name).then(function (data) {
                        file.uploadUrl = data;
                        done();
                    });
                }
            };
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.