XMLHttpRequest 无法加载 http://www.images.mysite.com/upload.php。请求的资源上不存在 'Access-Control-Allow-Origin' header
XMLHttpRequest cannot load http://www.images.mysite.com/upload.php. No 'Access-Control-Allow-Origin' header is present on the requested resource
我正在从我的网站 www.mysite.com
.www.mysite.com
.
上的应用程序 运行ning 上传文件到我的子域 images.mysite.url
为此,我使用 dropzone 进行 AJAX 文件上传和 PHP。
选择文件后,它在上传页面和控制台
显示消息 Server responded with 0 code.
XMLHttpRequest cannot load http://www.images.mysite.com/upload.php. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8085' is therefore not allowed access.
(出于测试目的,我先在本地主机上 运行 上传到服务器后的相同消息)
在服务器上,我的upload.php:
<?php
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept");
header('Access-Control-Allow-Methods: GET, POST, PUT');
header('content-type: application/json; charset=utf-8');
$uploaddir = '/post/';
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
echo '<pre>';
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
echo "File is valid, and was successfully uploaded.\n";
} else {
echo "Possible file upload attack!\n";
}
echo 'Here is some more debugging info:';
print_r($_FILES);
print "</pre>";
?>
空投区
$("i#dzopen").dropzone({
paramName: "file",
maxFilesize: 10,
url: 'http://www.images.mysite.com/upload.php',
previewsContainer: "#media-upload-previews",
uploadMultiple: true,
parallelUploads: 1,
dataType: 'jsonp',
maxFiles: 10,
acceptedFiles: "image/*,audio/*,video/*",
init: function () {
this.on("success", function (file, responseText) {
log("log " + responseText);
});
}
});
如何解决问题?
按原样使用您的代码,Access-Control-Allow-Origin
header 应该已经发送。
您可能遇到服务器错误,或其他原因导致无法发送 header(header 已发送?内容已刷新?错误 URL?)。
查看您的控制台和浏览器的开发人员工具网络选项卡是否存在错误,并查看 headers。
在修复阻止发送 header 表单的任何问题后,请考虑以下事项:
Dropzone 发送一个
Access-Control-Request-Headers:accept, cache-control, content-type, x-requested-with
header。您没有回复 cache-control
已接受,因此您需要添加它:
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Cache-Control");
您允许 uploadMultiple
,但只需要一个文件。
- 您在 dropzone 配置中指定的
paramName
与您在服务器上使用的不同("file"
与 'userfile'
)。
- 您的服务器没有 return 有效 JSON,这是 dropzone 处理程序所期望的。
一个可以帮助您入门的人为示例(不要在生产中使用!):
<?php
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Cache-Control");
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PUT');
header('content-type: application/json; charset=utf-8');
$uploaddir = '/post/';
$idx = "file";
$res = array("success" => true, "status" =>array());
if (isset($_FILES[$idx]) && is_array($_FILES[$idx])) {
foreach ($_FILES[$idx]["error"] as $key => $error) {
$status = array("success" => true);
if ($error == UPLOAD_ERR_OK) {
$tmp_name = $_FILES[$idx]["tmp_name"][$key];
$name = $_FILES[$idx]["name"][$key];
if (move_uploaded_file($tmp_name, $uploaddir.$name)) {
$status["message"] = "ok";
} else {
$res["success"] = false;
$status["success"] = false;
$status["error"] = error_get_last();
$status["message"] = "internal server error";
}
} else {
$res["success"] = false;
$status["success"] = false;
$status["error"] = $error;
$status["message"] = "upload error";
}
$res["status"][] = $status;
}
}
echo(json_encode($res));
编辑:
原来是服务器问题。 Apache 的 _mod_security_ 阻止了文件上传,但不是正常的 POST 或 GET 请求,并且 returned 406 Not Acceptable
.
发行
$ curl http://example.com/upload.php -X POST \
-F "file[]=@/path/to/file" \
-v
结果
> POST /upload.php HTTP/1.1
> User-Agent: curl/7.35.0
> Host: images.sitename.com
> Accept: */*
> Content-Length: 719
> Expect: 100-continue
> Content-Type: multipart/form-data; boundary=------------------------755cbe89e26cbeb1
>
< HTTP/1.1 100 Continue
< HTTP/1.1 406 Not Acceptable
* Server nginx admin is not blacklisted
< Server: nginx admin
< Date: Mon, 19 Oct 2015 08:06:59 GMT
< Content-Type: text/html; charset=iso-8859-1
< Connection: keep-alive
< Content-Length: 380
* HTTP error before end of send, stop sending
<
(nginx 充当 reverse-proxy,Apache 在其后面)。
在这种情况下,如果您自己管理服务器,您可以使用 .htaccess 或其他方式禁用有问题的规则:
方法 1 - 完全禁用 mode_security 文件(不太推荐)
<IfModule mod_security2.c>
SecRuleEngine Off
</IfModule>
方法 2 - 禁用特定规则
$ cat /var/log/apache2/error.log | grep ModSecurity
(修改路径以指向您的 Apache 错误日志),它应该 returns 像这样的行:
[<date>] [error] [client <...>] ModSecurity: Access denied with code 406 (phase 2). <...> at REQUEST_FILENAME. [file <...>] [id "950004"] [msg <...>] <...>
注意 [id "950004"]
。
可以通过以下方式禁用它:
<IfModule mod_security2.c>
SecRuleRemoveById 950004
</IfModule>
还有其他可能更好的方法。
我正在从我的网站 www.mysite.com
.www.mysite.com
.
images.mysite.url
为此,我使用 dropzone 进行 AJAX 文件上传和 PHP。 选择文件后,它在上传页面和控制台
显示消息Server responded with 0 code.
XMLHttpRequest cannot load http://www.images.mysite.com/upload.php. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8085' is therefore not allowed access.
(出于测试目的,我先在本地主机上 运行 上传到服务器后的相同消息)
在服务器上,我的upload.php:
<?php
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept");
header('Access-Control-Allow-Methods: GET, POST, PUT');
header('content-type: application/json; charset=utf-8');
$uploaddir = '/post/';
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
echo '<pre>';
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
echo "File is valid, and was successfully uploaded.\n";
} else {
echo "Possible file upload attack!\n";
}
echo 'Here is some more debugging info:';
print_r($_FILES);
print "</pre>";
?>
空投区
$("i#dzopen").dropzone({
paramName: "file",
maxFilesize: 10,
url: 'http://www.images.mysite.com/upload.php',
previewsContainer: "#media-upload-previews",
uploadMultiple: true,
parallelUploads: 1,
dataType: 'jsonp',
maxFiles: 10,
acceptedFiles: "image/*,audio/*,video/*",
init: function () {
this.on("success", function (file, responseText) {
log("log " + responseText);
});
}
});
如何解决问题?
按原样使用您的代码,Access-Control-Allow-Origin
header 应该已经发送。
您可能遇到服务器错误,或其他原因导致无法发送 header(header 已发送?内容已刷新?错误 URL?)。
查看您的控制台和浏览器的开发人员工具网络选项卡是否存在错误,并查看 headers。
在修复阻止发送 header 表单的任何问题后,请考虑以下事项:
Dropzone 发送一个
Access-Control-Request-Headers:accept, cache-control, content-type, x-requested-with
header。您没有回复
cache-control
已接受,因此您需要添加它:header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Cache-Control");
您允许
uploadMultiple
,但只需要一个文件。- 您在 dropzone 配置中指定的
paramName
与您在服务器上使用的不同("file"
与'userfile'
)。 - 您的服务器没有 return 有效 JSON,这是 dropzone 处理程序所期望的。
一个可以帮助您入门的人为示例(不要在生产中使用!):
<?php
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Cache-Control");
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PUT');
header('content-type: application/json; charset=utf-8');
$uploaddir = '/post/';
$idx = "file";
$res = array("success" => true, "status" =>array());
if (isset($_FILES[$idx]) && is_array($_FILES[$idx])) {
foreach ($_FILES[$idx]["error"] as $key => $error) {
$status = array("success" => true);
if ($error == UPLOAD_ERR_OK) {
$tmp_name = $_FILES[$idx]["tmp_name"][$key];
$name = $_FILES[$idx]["name"][$key];
if (move_uploaded_file($tmp_name, $uploaddir.$name)) {
$status["message"] = "ok";
} else {
$res["success"] = false;
$status["success"] = false;
$status["error"] = error_get_last();
$status["message"] = "internal server error";
}
} else {
$res["success"] = false;
$status["success"] = false;
$status["error"] = $error;
$status["message"] = "upload error";
}
$res["status"][] = $status;
}
}
echo(json_encode($res));
编辑:
原来是服务器问题。 Apache 的 _mod_security_ 阻止了文件上传,但不是正常的 POST 或 GET 请求,并且 returned 406 Not Acceptable
.
发行
$ curl http://example.com/upload.php -X POST \
-F "file[]=@/path/to/file" \
-v
结果
> POST /upload.php HTTP/1.1
> User-Agent: curl/7.35.0
> Host: images.sitename.com
> Accept: */*
> Content-Length: 719
> Expect: 100-continue
> Content-Type: multipart/form-data; boundary=------------------------755cbe89e26cbeb1
>
< HTTP/1.1 100 Continue
< HTTP/1.1 406 Not Acceptable
* Server nginx admin is not blacklisted
< Server: nginx admin
< Date: Mon, 19 Oct 2015 08:06:59 GMT
< Content-Type: text/html; charset=iso-8859-1
< Connection: keep-alive
< Content-Length: 380
* HTTP error before end of send, stop sending
<
(nginx 充当 reverse-proxy,Apache 在其后面)。 在这种情况下,如果您自己管理服务器,您可以使用 .htaccess 或其他方式禁用有问题的规则:
方法 1 - 完全禁用 mode_security 文件(不太推荐)
<IfModule mod_security2.c>
SecRuleEngine Off
</IfModule>
方法 2 - 禁用特定规则
$ cat /var/log/apache2/error.log | grep ModSecurity
(修改路径以指向您的 Apache 错误日志),它应该 returns 像这样的行:
[<date>] [error] [client <...>] ModSecurity: Access denied with code 406 (phase 2). <...> at REQUEST_FILENAME. [file <...>] [id "950004"] [msg <...>] <...>
注意 [id "950004"]
。
可以通过以下方式禁用它:
<IfModule mod_security2.c>
SecRuleRemoveById 950004
</IfModule>
还有其他可能更好的方法。