简体   繁体   中英

XMLHttpRequest cannot load http://www.images.mysite.com/upload.php. No 'Access-Control-Allow-Origin' header is present on the requested resource

I am uploading files in mysubdomain images.mysite.url from application running on my site www.mysite.com .

For this I am using dropzone for AJAX file upload and PHP. After selecting file it is showing message the Server responded with 0 code. at upload page and at console

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.

(for testing purpose, I first run on localhost same message after uploading to server)

On the server, my 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>";

?>

Dropzone

$("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);
                       });                   
                }
            });

How to resolve the problem?

With your code as is, the Access-Control-Allow-Origin header should have been sent.

You may have a server error, or something else that prevents the headers from being sent (headers already sent? content flushed? wrong URL?).

Look at your console and browser's developer tools network tab for errors and look at the headers.

After you fix whatever it is that prevented the headers form being sent, consider the following:

  1. Dropzone sends a

    Access-Control-Request-Headers:accept, cache-control, content-type, x-requested-with

    header. You don't reply with cache-control accepted, so you will need to add it:

     header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Cache-Control"); 
  2. You allow uploadMultiple , but only expect a single file.

  3. The paramName that you specify in your dropzone config is different from the one that you use on the server ( "file" vs 'userfile' ).
  4. Your server does not return valid JSON, which the dropzone handler expects.

A contrived example that might get you started (don't use in production!):

<?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));

Edit:

Turns out there was a server issue. Apache's _mod_security_ had blocked the file uploads, but not normal POST or GET requests, and returned 406 Not Acceptable .

Issuing

$ curl http://example.com/upload.php -X POST \
  -F "file[]=@/path/to/file" \
  -v

resulted in

> 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 serves as a reverse-proxy and Apache is behind it). In such case, if you manage the server yourself, you can disable the problematic rule using .htaccess , or in other ways:

Method 1 - completely disable mode_security for the file (less recommended)

<IfModule mod_security2.c>
  SecRuleEngine Off 
</IfModule>

Method 2 - disable specific rule

$ cat /var/log/apache2/error.log | grep ModSecurity

(modify the path to point to your Apache error log), which should returns lines like this one:

[<date>] [error] [client <...>] ModSecurity: Access denied with code 406 (phase 2). <...> at REQUEST_FILENAME. [file <...>] [id "950004"] [msg <...>] <...>

Note the [id "950004"] .

It can be disabled via:

<IfModule mod_security2.c>
    SecRuleRemoveById 950004 
</IfModule>

There are other, potentially better, ways of doing this.

Here is a good reference for mod_security configuration .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM