跨域上传


本插件支持两种跨​​站点(跨域)文件上传的方法:

  • 跨域 XMLHttpRequest 文件上传
  • 跨域 iframe 传输上传
注意:任何类型的服务端程度都具备完整的跨域支持。

跨域 XMLHttpRequest 文件上传


跨域 XHR 文件上传除了需要一个支持 XHR 文件上传的浏览器,便无需客户端再进行任何工作 - 请参阅浏览器支持

要允许跨域 XHR 文件上传,目标服务端需设置正确的 Access-Control-Allow-Origin header,例如:

Access-Control-Allow-Origin: http://example.org
注意: 为了做好浏览器兼容,header 必须设置为既能响应文件上传请求(POST),也能响应 OPTIONS 请求。有关详细信息,请参阅 Preflighted requests

如果 multipart 配置项设为 false 或启用 分块上传,你还需要设置 Access-Control-Allow-Headers 以允许插件可以使用自定义 header 来传输文件元信息:

Access-Control-Allow-Headers: Content-Type, Content-Range, Content-Disposition, Content-Description

如果你需要发送 cookie(例如用于身份验证),请将 $.ajax() 设置项的 withCredentials 作为插件配置项一同设置:

$('#fileupload').fileupload('option', {
    xhrFields: {
        withCredentials: true
    }
});

在服务端,你需要将 header Access-Control-Allow-Credentials 设置为 true

Access-Control-Allow-Origin: http://example.org
Access-Control-Allow-Credentials: true
注意: 在响应凭据请求时,服务端必须指定域名,且不能使用通配符“*”。

在服务端设置正确的标头后,跨域 XHR 文件上传就和同域名内上传一样了。

跨域 iframe 传输上传


要强制浏览器使用 iframe 传输模块进行文件上传,可以将 forceIframeTransport 配置项设置为 true

$('#fileupload').fileupload({
    forceIframeTransport: true
});

跨域 iframe 传输上传不需要服务端设置额外的响应 header。

不过遗憾的是,iframe 方式无法从其他域名的响应中获取 body 内容。

因此,跨域 iframe 传输上传需要传递一个溯源重定向地址用来检索上传结果。将 redirect 配置项设为 result.html 文件的绝对 url,该文件必须位于源服务器上:

$('#fileupload').fileupload(
    'option',
    'redirect',
    'http://example.org/result.html?%s'
);

如果文件是跨域 iframe 传输上传的,插件会将通过 redirect 配置的绝对 URL 作为 formData 的一部分进行传输。如果配置项未设置 redirectParamName,表单中将使用 redirect 作为上述内容的参数名。对于 XHR 文件上传方式或同域名内上传,redirect 配置项会被直接忽略。

在服务端,你需要检查请求参数中是否带有 redirect。在这种情况下,服务端的响应必须重定向到该参数指定的地址,并将结果内容以 URL 编码方式附加到该 URL 上。请注意,传到服务端的重定向参数应有一个占位符(例如 %s)作为 URL 的一部分,这样服务端才可以把编码后的结果替换到该占位符上。

然后 result.html 页面再将结果内容解码后视为 body 内容。这允许插件能够得到响应而不会出现跨域访问问题。

示例,发送回客户端的重定向 URL:

http://example.org/result.html?%7B%22files%22%3A%5B%7B%22name%22%3A%22cat.jpg%22%2C%22size%22%3A464885%2C%22type%22%3A%22image%2Fjpeg%22%2C%22url%22%3A%22http%3A%2F%2Fexample.org%2Ffiles%2Fcat.jpg%22%2C%22thumbnail_url%22%3A%22http%3A%2F%2Fexample.org%2Ffiles%2Fthumbnail%2Fcat.jpg%22%2C%22delete_url%22%3A%22http%3A%2F%2Fexample.org%2F%3Ffile%3Dcat.jpg%22%7D%5D%7D

示例,由 result.html 页面解码的 body 内容:

{"files":[{"name":"cat.jpg","size":464885,"type":"image/jpeg","url":"http://example.org/files/cat.jpg","thumbnail_url":"http://example.org/files/thumbnail/cat.jpg","delete_url":"http://example.org/?file=cat.jpg"}]}
注意: 响应不应超过特定长度,因为重定向 URL 受到浏览器 URL 最大长度的限制。(最大长度限制是多少?译者注:IE 2083 字符,FF 65536 字符,Safari 80000 字符,Opera 190000 字符,Google Chrome 8182 字符。另外,Web Server 也会限制 URL 长度。)
次级域名的跨域 iframe 传输上传 HTML 响应

如果托管上传表单的服务器和文件上传的目标服务器这两台服务器只是在不同的子域上(例如,source.example.org 和 target.example.org),可以通过将以下 Javascript 代码添加到两边网页(上传表单页面和上传服务器响应页面)来访问子域上的 iframe 内容:

document.domain = 'example.com';
请注意,这要求服务端响应的是 HTML 文档,而不是 JSON,这是插件 UI 组件的默认方式。

跨域扩展资源


本插件库还为 CORS(cross-origin-resource-sharing) 跨源资源共享提供了两个额外的脚本。

译者注:位于 js/cors 的 jquery.xdr-transport.js 和 jquery.postmessage-transport.js。
XDomainRequest 传输组件

仅在 IE8+ 引用 XDomainRequest 传输组件:

<!-- The XDomainRequest Transport is included for cross-domain file deletion for IE8+ -->
<!--[if gte IE 8]><script src="js/cors/jquery.xdr-transport.js"></script><![endif]-->

XDomainRequest 传输能让 IE8+ 支持跨域 GET 和 POST AJAX 请求。但是,由于 IE 不支持 AJAX 文件上传,所以它不允许跨域文件上传。

PostMessage 传输组件

PostMessage 传输是为 XHR 跨域上传提供的另一种方法,它不需要任何 cross-domain header,但需要目标服务器上实现 postMessage API

PostMessage 传输postMessage API 利用 window.postMessage() 方法在两个不同的域名间传输文件。

通过引用 PostMessage 传输脚本来使用它:

<script src="js/cors/jquery.postmessage-transport.js"></script>

然后将 postMessage 配置项设为目标服务器上 postMessage API 的位置:

$('#fileupload').fileupload(
    'option',
    'postMessage',
    'http://example.org/postmessage.html'
);

PostMessage API 拥有一项配置来允许源端主机上传文件。请把该配置以正则表达式的格式设为你希望使用的域名。

注意:目前只有 Google Chrome 完全支持 PostMessage 传输上传。