-
-
Save getify/3167492 to your computer and use it in GitHub Desktop.
| var xhr, form_data = new FormData(); | |
| xhr = new XMLHttpRequest(); | |
| xhr.open("POST","http://barfoo.com/upload"); | |
| xhr.setRequestHeader("Content-Type","multipart/form-data"); | |
| xhr.setRequestHeader("File-Name",file.name); | |
| xhr.setRequestHeader("File-Size",(file.size || file.fileSize)); | |
| xhr.setRequestHeader("File-Type",file.type); | |
| xhr.setRequestHeader("Session-ID",12345); | |
| xhr.onreadystatechange = function __xhr_onreadystatechange__(){ | |
| if (xhr.readyState == 4) { | |
| xhr.onreadystatechange = null; | |
| if (xhr.status != 200 || xhr.responseText != "OK") { | |
| alert("Sorry, upload failed for: " + (file.name || "[unknown file]")); | |
| } | |
| xhr = null; | |
| } | |
| }; | |
| form_data.append(file.name,file); | |
| xhr.send(form_data); |
| events.js:66 | |
| throw arguments[1]; // Unhandled 'error' event | |
| ^ | |
| Error: bad content-type header, no multipart boundary | |
| at IncomingForm._parseContentType (/path/to/node_modules/formidable/lib/incoming_form.js:233:19) | |
| at IncomingForm.writeHeaders (/path/to/node_modules/formidable/lib/incoming_form.js:131:8) | |
| at IncomingForm.parse (/path/to/node_modules/formidable/lib/incoming_form.js:84:8) |
| Content-Type:multipart/form-data | |
| File-Name:blah.jpg | |
| File-Size:29080 | |
| File-Type:image/jpeg | |
| Origin:http://foobar.com | |
| Referer:http://foobar.com/blah/ | |
| Session-ID:12345 | |
| User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/537.2 (KHTML, like Gecko) Chrome/22.0.1215.0 Safari/537.2 | |
| Request Payload | |
| ------WebKitFormBoundary3KzOjhaAGvJbm65r | |
| Content-Disposition: form-data; name="blah.jpg"; filename="blah.jpg" | |
| Content-Type: image/jpeg | |
| ------WebKitFormBoundary3KzOjhaAGvJbm65r-- |
| // handle the HTTP routing | |
| function handleHTTP(req, res) { | |
| // handle file uploads | |
| if (req.url == "/upload") { | |
| // handle the CORS preflight request for the upload | |
| if (req.method.toLowerCase() == "options" && req.headers["access-control-request-method"].toLowerCase() == "post") { | |
| res.writeHead(200,CORS_POST_HEADERS); | |
| res.end(); | |
| return; | |
| } | |
| // are we doing a POST upload? | |
| else if (req.method.toLowerCase() == "post") { | |
| // add the CORS POST headers | |
| for (header in CORS_POST_HEADERS) { | |
| res.setHeader(header,CORS_POST_HEADERS[header]); | |
| } | |
| // parse a file upload | |
| var form = new formidable.IncomingForm(); | |
| form.parse(req,function __form_parse_cb__(err,fields,files) { | |
| if (err) { | |
| res.writeHead(500, {"Content-Type": "text/plain"}); | |
| res.end(); | |
| console.log("upload err: " + JSON.stringify(err)); | |
| } | |
| else { | |
| console.log(JSON.stringify(files)); | |
| res.writeHead(200, {"Content-Type": "text/plain"}); | |
| res.write("OK"); | |
| res.end(); | |
| } | |
| }); | |
| return; | |
| } | |
| // otherwise, bail because we won't handle this kind of request! | |
| else { | |
| // add the CORS POST headers | |
| for (header in CORS_POST_HEADERS) { | |
| res.setHeader(header,CORS_POST_HEADERS[header]); | |
| } | |
| res.writeHead(403,{"Content-Type": "text/plain"}); | |
| res.end(); | |
| return; | |
| } | |
| } | |
| return false; | |
| } | |
| require("http").createServer(handleHTTP).listen(80); |
Ah, that makes sense. I guess the browser generates a random boundary value and appends it to the content-type. @getify have you tried leaving the content-type off to see if the xhr does the right thing? If not, you'll have to find a way to get the generated boundary and append it to the content-type. Or you'll have to generate your own boundary value and have the body use that value. I'd be interested to know how you got this working.
I took out the setting of the the content-type on the XHR object, and sure enough the browser automatically sets the content-type, including the boundary, and all works fine. Thanks for the hint, @polotek and @alFReD-NSH!
Side note: apparently you have to return CORS headers on every single response, not just in response to the preflight OPTIONS request. Had to fix that too.
Here's the error: https://github.com/felixge/node-formidable/blob/master/lib/incoming_form.js#L242
Seems like your content type should have boundary in it somewhere.