跨域 上传文件 的一个例子

web端:

                var xhr = new XMLHttpRequest();
                /**
                 * handle callback
                 */
                xhr.onreadystatechange = onreadystatechange;
                /**
                 * progress
                 */
                xhr.upload.onprogress = handleProgress;
                /**
                 * true is using async; sync is deprecated
                 */
                xhr.open('POST', uri, true);
                /**
                * form data
                */
                xhr.send(filedata);

服务器端(nodejs):

var formidable = require('formidable'),
    http = require('http'),
    util = require('util');

http.createServer(function (req, res) {
    console.log('get the req');
    console.log('req ::' + req);
    if (req.url == '/upload' && req.method.toLowerCase() == 'post') {
        // parse a file upload
        var form = new formidable.IncomingForm();

        form.parse(req, function (err, fields, files) {
            res.writeHead(200, {
                'Access-Control-Allow-Methods': 'OPTIONS, HEAD, POST',
                'Access-Control-Allow-Origin': '*',
            });
            res.write('received upload:\n\n');
            res.end(util.inspect({ fields: fields, files: files }));
        });

        return;
    } else if (req.url == '/upload' && req.method.toLowerCase() == 'options') {
        // parse a file upload
        res.writeHead(200, {
            'Access-Control-Allow-Methods': 'OPTIONS, HEAD, POST',
            'Access-Control-Allow-Origin': '*',
        });
        res.write('received upload:\n\n');
        res.end();
        return;
    }


}).listen(9000);

这里有个问题就是当跨域监听上传进度的时候,会抛出prelight no ‘Access-control-allow-origin’in response之类的错误,
这是因为webkit和firefox浏览器会自动发送一个OPTIONS的请求到服务器。服务器需要对这个请求也设置成跨域的。

I ended up checking out the Webkit source code in an attempt to figure this out (after Google did not yield any helpful hits). It turns out that Webkit will force any cross-origin request to be preflighted simply if you register an onprogress event handler. I’m not entirely sure, even after reading the code comments, why this logic was applied.

In XMLHttpRequest.cpp:

void XMLHttpRequest::createRequest(ExceptionCode& ec)
{

options.preflightPolicy = uploadEvents ? ForcePreflight : ConsiderPreflight;

...

// The presence of upload event listeners forces us to use preflighting because POSTing to an URL that does not
// permit cross origin requests should look exactly like POSTing to an URL that does not respond at all.
// Also, only async requests support upload progress events.
bool uploadEvents = false;
if (m_async) {
    m_progressEventThrottle.dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadstartEvent));
    if (m_requestEntityBody && m_upload) {
        uploadEvents = m_upload->hasEventListeners();
        m_upload->dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadstartEvent));
    }
}

...

}

UPDATE: Firefox applies the same logic as Webkit, it appears. Here is the relevant code from nsXMLHttpRequest.cpp:

nsresult
nsXMLHttpRequest::CheckChannelForCrossSiteRequest(nsIChannel* aChannel)
{

// Check if we need to do a preflight request.
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
NS_ENSURE_TRUE(httpChannel, NS_ERROR_DOM_BAD_URI);

nsAutoCString method;
httpChannel->GetRequestMethod(method);
if (!mCORSUnsafeHeaders.IsEmpty() ||
    (mUpload && mUpload->HasListeners()) ||
    (!method.LowerCaseEqualsLiteral("get") &&
     !method.LowerCaseEqualsLiteral("post") &&
     !method.LowerCaseEqualsLiteral("head"))) {
  mState |= XML_HTTP_REQUEST_NEED_AC_PREFLIGHT;
}

...

}
Notice the mUpload && mUpload->HasListeners() portion of the conditional.

Seems like Webkit and Firefox (and possibly others) have inserted some logic into their preflight-determination code that is not sanctioned by the W3C spec. If I’m missing something in the spec, please comment.

同时如果后台使用的是springMVC,要在web.xml中添加下述配置

<init-param>
<param-name>dispatchOptionsRequest</param-name>
<param-value>true</param-value>
</init-param>

具体详见
默认Spring DispatcherServlet 不支持 OPTIONS方法

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值