jQuery跨域文件上传
Posted
技术标签:
【中文标题】jQuery跨域文件上传【英文标题】:Cross domain file upload with jQuery 【发布时间】:2015-04-06 13:47:15 【问题描述】:我的代码在同一个域中运行良好。 但是当我使用 dataType: 'jsonp' & crossDomain: true 在跨域上尝试它时 代码示例 -
var fa = new FormData();
fa.append("upload_pass", document.getElementById("upload_pass").files['0']);
$.ajax(
url: 'http://xxx.xx.xx.xx/upload.php',
data: fa,
contentType: false,
processData: false,
dataType: 'jsonp',
crossDomain: true,
type: 'GET',
success: function(data)
alert(data);
);
是否存在任何概念理解差距或编码问题。 请提出建议。
【问题讨论】:
您无法使用 JSONP (GET) 请求上传文件。你需要 POST。对于跨域,在接收服务器上实现 CORS。 JSONP 不适用于 POST。crossDomain: true
只是禁用额外的标头,就像您发出跨域请求一样。它在那里,以便您可以向同一来源发出请求,然后 HTTP 重定向到不同的来源,而不会使其成为复杂的请求。您几乎不需要使用它。
【参考方案1】:
无法通过 GET 上传文件。即使您将使用 JSONP。 JSONP 仅适用于 GET 请求。而且你不能用 GET 请求上传文件(通常是用 POST 请求上传文件)。
如果您想向某个服务器发送跨域 POST 请求,那么您应该确定在下一种情况下:
该服务器应该向您发送标头Access-Control-Allow-Origin : *
。此外,您可能需要Access-Control-Allow-Methods: POST
标头。
如果它有这些标头,那么你很幸运,你可以在这个服务器上发布你的数据。
附:您可以尝试使用其他方法发出有效的跨域请求。很好的js library easyXDM 用于跨域请求,女巫使用不同的方式来做到这一点。
【讨论】:
当我不附加upload.onprogress 事件处理程序时,你知道为什么上传文件的POST 到同一个域但不同的端口有效吗?添加 upload.onprogress 会清除帖子和标题,但如果没有事件处理程序,文件上传就好了。【参考方案2】:JSONP 和 CORS 完全是两个不同的东西。
JSONP
带有 Padding 的 JSON 只是利用下载 javascript 文件时没有同源策略限制这一事实的一种技巧。由于您只能下载脚本,因此我们使用内置数据格式 JSON 而不是 XML 或 html。此外,您只能使用 JSONP 发出 GET 请求,因为它所做的只是创建一个 script
并将 src
设置为其他域并将其附加到您的 DOM,一旦下载,它就会被执行,这就是使用我们的回调的时候从传递 JSON 对象的原始域调用代码。
CORS
跨域资源共享是 W3C 的一项标准,它允许从另一个域请求网页上的许多资源(例如字体、JavaScript 等)。您不仅可以使用 GET,还可以使用所有常用的 HTTP 方法,如 POST、HEAD、PUT、DELETE 等
如何提出 CORS 请求:
就像将 AJAX 调用中的 url 更改为其他域一样简单,这就是客户端没有其他更改。
如果您的浏览器支持 CORS,则根据请求的类型(简单/复杂),可能会触发飞行前 OPTIONS 请求,以获取有关此域和此域允许的方法和内容类型类型的信息OPTIONS 响应将被缓存。
接下来,每当您对其他域进行 AJAX 调用时,浏览器都会在后台发送一个 Origin
请求标头。例如,如果来自 google 的页面对 facebook 进行 AJAX 调用,则会将类似这样的内容添加到请求标头中
Origin: http://google.com
当 facebook 看到此标头时,它将检查 google.com 是否在其允许主机的有效列表中,并通过发送以下标头作为响应来同意这一点。
Access-Control-Allow-Origin: http://google.com
请注意,Origin 和 Allow-Origin 标头中的主机名应匹配,以便浏览器接受并处理收到的响应。您甚至可以通过在响应中设置以下标头来限制允许的方法和自定义标头
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER
最后回答您的问题,如下更改您的 Ajax 定义
$.ajax(
url: 'http://some-other-domain.com/upload.php',
data: fa,
contentType: false,
processData: false,
type: 'POST',
success: function(data)
alert(data);
);
由于您只是使用文件进行简单的 POST 调用,因此它是一个简单的请求,因此 Allow-Origin 标头就足够了。在您的 PHP 中,阅读 Origin
标头检查它是否在您的列表中,并在 Allow-Origin 响应标头中设置相同的标头值。我不知道 PHP,但希望是这样的 :)
<?php
$headers = apache_request_headers();
foreach ($headers as $header => $value)
if($header == "Origin")
/* check if $value is in your list
if yes, set the response header */
header('Access-Control-Allow-Origin: $value');
/* adding just this header will allow any method from this
domain, in case you need to allow only POST method add
Access-Control-Allow-Methods header as well */
break;
// do the remaining processing of request
?>
更多资源
History of CORS 5 min video on CORS Pre-flighted requests for complex CORS requests希望这能回答你的问题:)
【讨论】:
哇,伙计,这个问题的信息真的很全面。 上周我看到很多关于这个话题的问题,以及我们中的许多人经常感到困惑。所以我想分享一些我知道的事情:-)【参考方案3】:您不能使用除 GET 之外的 JSONP 发出任何类型的请求。您不能使用 GET 请求上传文件(除非它是一个非常小的文件,您可以使用 JavaScript 读取并转换为可以视为常规表单数据的字符串)。
您需要切换到使用带有 CORS(或同源代理)的 POST 来禁用同源策略。
【讨论】:
【参考方案4】:对于跨域工作,您需要这些东西 -
1 :- 您需要服务器的许可。像 Access-Control-Allow-Origin 一样:*.
2 :- 如果您使用的是 jquery,那么您可以使用 jsonp 方法。
3 :- 如果你想使用纯 javascript,那么你可以使用这个链接 -
How to make a JSONP request from Javascript without JQuery?
【讨论】:
【参考方案5】:正如人们所说 - GET 不是做到这一点的方法。我已经看到这种事情是通过隐藏的 iFrame 完成的。您可能可以找到各种 jQuery 插件来实现所需的结果,但我发现有一个名为“jQuery iFrame Transport”https://cmlenz.github.io/jquery-iframe-transport/ 希望对您有所帮助。
【讨论】:
【参考方案6】:您不能使用 JSONP 或使用 GET 请求上传文件。你确定它之前是为同一个来源工作的吗?
您必须发送跨域 XHR 请求才能上传文件。您可以为此使用 JQuery 文件上传。 https://github.com/blueimp/jQuery-File-Upload/wiki/Cross-domain-uploads
【讨论】:
以上是关于jQuery跨域文件上传的主要内容,如果未能解决你的问题,请参考以下文章
Angular4 后台管理系统搭建(10) - 做一个通用的可跨域上传文件的组件