Skip to content

Conversation

@jbcpollak
Copy link
Contributor

Hello, I've extracted upload tagParams and upload url functionality into their own functions, this will facilitate frameworks like Angular fetching the server-side params.

The reason for doing this is so I could make a server-side service like:

/cloudinary/requestUploadAuthorization

which returns the signed upload params and upload URL. Then the client side framework (Angular in this case) composes the correct tag and handles all the JS processing.

An alternative would have been for the server-side service to return the fully formed tag, but this seemed less clean in the context of Angular or another framework which composes its own HTML widgets.

In either case, this is a rather harmless change which makes it possible to independently test these portions of the code in the future.

…nctions, this will facilitate frameworks like Angular fetching the server-side params
@TalLevAmi
Copy link
Contributor

Sounds like a good idea. Wouldn't it make more sense to return the JSON object without HTML escaping it? The service you are describing will probably return JSON and the JS will have an easier time working with JSON.

@pulkitsinghal
Copy link

@jbcpollak What do you mean by the word signed in the sentence which returns the signed upload params and upload URL ... you've got me curious.

@jbcpollak
Copy link
Contributor Author

@TalLevAmi , the reason I did kept the JSON escaping in Cloudinary is because I wanted my service which returns JSON to treat the data returned as a String, so I could just that as 'params', and just stick that straight into the HTML element's attribute.

For example, here is what my service returns:

{
  "code": 200,
  "params": "{"tags":"employerId_9972,companyLogoPhotouploadedBy_EMPLOYER_321024,domain_josh.elisto.us,employerId_9972,companyLogoPhoto","transformation":"c_scale,h_2048,w_2048","timestamp":"1375451368","api_key":"944777949387271","callback":"http:\\\/\\\/josh.elisto.us\\\/resources\\\/utilities\\\/cloudinary\\\/cloudinary_cors.html","signature":"92a64c98c349616e14dd58f7ef43135ac1167982"}",
  "url": "https:\/\/api.cloudinary.com\/v1_1\/assured-labor\/image\/upload",
  "statusMessage": "OK"
}

I thought this was easier than returning the params as a JSON object itself, and then having to escape it on the client side. I guess I could go either way, I just don't know how to escape it on the client side and the existing code was already doing the escaping.

@pulkitsinghal, Cloudinary requires the client-side upload parameters to be signed by your api_key, but your api_key should not be shared with the client. To get around this, the params object above includes a 'signature' property, which is generated from the other parameters and your api-key

@TalLevAmi
Copy link
Contributor

@jbcpollak I guess it depends on how you build the upload input tag. An HTML escaped version is only useful if you are building the tag using a template, and even then, won't Angular do the HTML escaping for you?

One thing to notice is that if you have an existing input tag and you want to set the formData with these parameters, then you will need the JS hash itself as explained here.

@jbcpollak
Copy link
Contributor Author

@TalLevAmi , Thanks, I don't quite follow you, what is the 'JS hash'? You mean the raw JS object? That would actually make the code simpler, because I wouldn't need to encode and then decode on the client side.

I had noticed the problem you mentioned already, my solution was to defer adding the "cloudinary-fileupload" class until the formData was supplied, and then manually calling cloudinary_fileupload() on the element after registering everything correctly.

I like your solution however, as long as it will be formally supported, I'll give that a go and submit an update.

I intend to publish the angular directives as soon as I have them worked out as well, but that will be in a few days.

…This allows the client-side to receive a JS hash / object directly. This is useful, depending on how the input is rendered.
@jbcpollak
Copy link
Contributor Author

@TalLevAmi, I moved the HTML escape back to imageUploadTag so we can get the unescaped JS. This is working well in my angular directive, except now the plugin is uploading to the wrong URL, so I need to debug that.

@jbcpollak
Copy link
Contributor Author

@TalLevAmi, I solved the URL problem by effectively running the following (its async, so the code is a bit more complicated):

element.fileupload({formData: params});
element.fileupload('option', 'url', url); //url value came from Uploader.java on the server

The request seems to be formulated correctly, but the POST call is consistently cancelled after 3 seconds with no response given. Is that something you could help me sort out?

@jbcpollak
Copy link
Contributor Author

Actually, it turns out the images are getting uploaded, but the client doesn't get a response.

I can see the images uploaded to my Cloudinary account, but neither Chrome nor Firefox have any data for the request Response, which is very strange.

Firefox shows a "302 Found" status code, but thats it.

@TalLevAmi
Copy link
Contributor

  1. You should be able to supply the url the same way you supply the formData, i.e.,

    element.fileupload({formData: params, url: url});

  2. If you get 302 it means the the server couldn't detect the request was AJAX and it assumes it was a form submit (e.g. in the iframe fallback), and redirects instead of returning the JSON. This usually means that the X-Requested-With header was not send. Try to add the following to your fileupload initialization (the Cloudinary JS code tries to do it, but maybe the manual initialization causes it not to be called at the right time):

    element.fileupload({..., headers: {"X-Requested-With": "XMLHttpRequest"}});

TalLevAmi pushed a commit that referenced this pull request Aug 4, 2013
Extracted upload tagParams and upload url functionality into their funct...
@TalLevAmi TalLevAmi merged commit 662885b into cloudinary:master Aug 4, 2013
@jbcpollak
Copy link
Contributor Author

Thanks for accepting the merge @TalLevAmi , with your tips I got upload working. I don't suppose I could convince you to release 1.0.6 with this change so I don't have to mess with an internal release? :)

When I sort out the callbacks I need for my other functionality, I'll share my angular directives separately.

For anyone who finds this thread in the future, here is my final initialization string:

                            element.fileupload({
                                formData: data.params,
                                url : data.url,
                                headers: {"X-Requested-With": "XMLHttpRequest"}
                            });

@TalLevAmi
Copy link
Contributor

Version 1.0.6 was just released to Sonatype. Should sync with Maven Central in a few hours. Notice that I changed the name of the extracted method. Thank you for you contribution.

@jbcpollak
Copy link
Contributor Author

Great, thanks @TalLevAmi !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants