如何避免文件上传时的CORS预检请求?

我使用jquery-fileupload来允许用户将文件上传到外部服务(Cloudinary更具体):

  $('.cloudinary-fileupload').fileupload();  

由于它是外部目标,浏览器会启动CORS请求。 但是,我注意到浏览器会预先设置CORS预检请求。 http://www.html5rocks.com/en/tutorials/cors/提供了关于何时触发预检请求以及何时未触发预检请求的非常好的见解。 据我所知,我的请求满足了作为CORS简单请求的所有标准(请参阅“CORS请求类型”一节 )。

发送到外部服务的文件上载请求

 POST /v1_1/wya/image/upload HTTP/1.1 Host: api.cloudinary.com Connection: keep-alive Content-Length: 22214 Accept: */* Origin: http://wya.herokuapp.com User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36 Content-Type: multipart/form-data; boundary=----WebKitFormBoundarym73rCIa6t8eTNkTa Referer: http://wya.herokuapp.com/ Accept-Encoding: gzip,deflate,sdch Accept-Language: sv-SE,sv;q=0.8,en-US;q=0.6,en;q=0.4,de;q=0.2 

在文件上载请求之前发送到外部服务的附加预检请求:

 OPTIONS /v1_1/wya/image/upload HTTP/1.1 Host: api.cloudinary.com Connection: keep-alive Access-Control-Request-Method: POST Origin: http://wya.herokuapp.com User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36 Access-Control-Request-Headers: accept, content-type Accept: */* Referer: http://wya.herokuapp.com/ Accept-Encoding: gzip,deflate,sdch Accept-Language: sv-SE,sv;q=0.8,en-US;q=0.6,en;q=0.4,de;q=0.2 

有没有办法避免这个额外的预检请求? 据我所知,文件上传请求是一个CORS简单请求,因为它是带有Content-Type multipart / form-data的HTTP POST,只有简单的请求HTTP头。


我想摆脱额外预检请求的原因是Cloudinary发送HTTP 302/304重定向作为对文件上传的响应。 浏览器不遵循这些重定向。 Chrome失败并显示以下消息:

 XMLHttpRequest cannot load https://api.cloudinary.com/v1_1/wya/image/upload. The request was redirected to 'http://wya.herokuapp.com/upload?bytes=21534&created_at=2014-02-12T09%3A04%3…d5b62ebb92b9236e5be6d472df242d016&type=upload&version=1392195882&width=723', which is disallowed for cross-origin requests that require preflight. 

问题是XHR头不会随着对Cloudinary的请求一起发送,导致Cloudinary重定向(IE回退)而不是返回JSON。 这通常是由于窗口小部件的初始化不正确引起的。 您通常不需要自己调用$('.cloudinary-fileupload').fileupload()因为这是由包含的Javascript完成的。 如果您仍需要手动初始化窗口小部件,请使用$('.cloudinary-fileupload').cloudinary_fileupload()