PDA

View Full Version : Upload binary file using form.submit()



bjnelson62
30 Nov 2012, 12:45 PM
I've got a form that has combo and filefield controls. When the user clicks Upload, the following code is executed:



form.submit({
url: myUrl,
headers: {'Content-Type':'multipart/mixed; charset=UTF-8'},
params: {
metadata: {'version' : '2.8.1.RELEASE'},
},
waitMsg: 'Uploading your image....',
success: function(form, action) {
VFABRIC.util.StatusBarWrapper.setGoodStatus('Successfully uploaded file: ' + action.result.file);
},
failure: function(form, action) {
switch (action.failureType) {
case Ext.form.action.Action.CLIENT_INVALID:
VFABRIC.util.StatusBarWrapper.setErrorStatus('Form fields may not be submitted with invalid values');
break;
case Ext.form.action.Action.CONNECT_FAILURE:
VFABRIC.util.StatusBarWrapper.setErrorStatus('Ajax communication failed');
break;
case Ext.form.action.Action.SERVER_INVALID:
VFABRIC.util.StatusBarWrapper.setErrorStatus(VFABRIC.util.AjaxWrapper.getServerErrorMsgs(action.response));
break;
}
me.up('window').destroy();
},
});


The server is unhappy, because it wants a metadata field. I tried to specify it in the code above, but obviously I'm not doing it correctly. Here's how the request should look:


POST /<product name>/v1/installation-images/
Content-Type: multipart/mixed; boundary=6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm
--6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm
Content-Disposition: form-data; name="metadata"
Content-Type: application/json;charset=UTF-8

{"version":"2.7.0.RELEASE"}
--6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm
Content-Disposition: form-data; name="data"; filename="installation-image.zip"
Content-Type: application/octet-stream
Content-Length: 7340032

<binary data>
--6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm--


Any ideas as to how I could structure the request to make the server happy? I know how the request should look, but I don't know how to achieve that look through the ExtJs library.

Is this even possible? I thought of using the Ext.Ajax() class directly, but then I run into the problem of not knowing the filename because the browser won't report it to the filefield control.

Thank you,

Brian

mitchellsimoens
3 Dec 2012, 4:51 AM
What does the request actually look?

bjnelson62
3 Dec 2012, 7:51 AM
What I posted earlier is exactly how the request should look; I didn't put it in the code brackets because technically it's not code, but I'll post it again:



POST /<product name>/v1/installation-images/
Content-Type: multipart/mixed; boundary=6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm
--6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm
Content-Disposition: form-data; name="metadata"
Content-Type: application/json;charset=UTF-8

{"version":"2.7.0.RELEASE"}
--6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm
Content-Disposition: form-data; name="data"; filename="installation-image.zip"
Content-Type: application/octet-stream
Content-Length: 7340032

<binary data>
--6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm--


My biggest issue (right now, don't know if there's another lurking beyond) is how to do the METADATA part. I've tried, but what I've tried so far was not palatable by the server.

Thanks,

bjnelson62
4 Dec 2012, 6:24 AM
Another way to express this is, is it possible to set the request headers on a form submission? So far I've been unsuccessful. In addition to what I already posted, I also tried this:



var boundary = '6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm',
parts = new Array();

parts.push('Content-Type: multipart/mixed; boundary=' + boundary);
parts.push('--' + boundary);
parts.push('Content-Disposition: form-data; name="metadata"');
parts.push('Content-Type: application/json;charset=UTF-8');
parts.push('{"version":"2.8.1.RELEASE"}');
parts.push('--' + boundary);
parts.push('Content-Disposition: form-data; name="data"; filename="installation-image.zip"');
parts.push('Content-Type: application/octet-stream');
parts.push('Content-Length: 7340032');
parts.push('--' + boundary);

form.submit({
url: myUrl,
headers: parts, //{'Content-Type':'multipart/mixed; charset=UTF-8'},
/*
params: {
metadata: {'version' : '2.8.1.RELEASE'},
},
*/
waitMsg: 'Uploading your image....',
success: function(form, action) {
me.up('window').destroy();
VFABRIC.util.StatusBarWrapper.setGoodStatus('Successfully uploaded file: ' + action.result.file);
},
failure: function(form, action) {
me.up('window').destroy();
switch (action.failureType) {
case Ext.form.action.Action.CLIENT_INVALID:
VFABRIC.util.StatusBarWrapper.setErrorStatus('Form fields may not be submitted with invalid values');
break;
case Ext.form.action.Action.CONNECT_FAILURE:
VFABRIC.util.StatusBarWrapper.setErrorStatus('Ajax communication failed');
break;
case Ext.form.action.Action.SERVER_INVALID:
VFABRIC.util.StatusBarWrapper.setErrorStatus(VFABRIC.util.AjaxWrapper.getServerErrorMsgs(action.response));
break;
}
},
});


It appears the headers I specify are totally ignored, based on what I see in the Network tab.

If this isn't possible, is there any other way I could do what I need to make the server happy? I'd prefer an Ext solution, but I'll accept a third party way (or rolling my own).

bjnelson62
4 Dec 2012, 8:40 AM
I found comments that indicate that headers are ignored when uploading a file. This should really be documented, it's crazy for developers (I'm not the only one) to be wasting time trying to get something to work that never will.

Is there any other way within Ext to get this to work? What are the third party options, if any?

bjnelson62
31 Dec 2012, 10:46 AM
So far as I know, there's no way to do this in ExtJS. I found some comments that indicate request headers are ignored on a file upload, and that was my experience too.

So instead I resorted to calling XMLHttpRequest. Also, I used FormData to add in the version metadata.

But I respectfully submit that anytime a customer has to go outside your framework to do something, you've failed. I know, I've worked on SCM systems in the past.

Brian