【问题标题】:HTML POST -> redirect working, XMLHTTPrequest -> redirect not working (Cannot make any requests from null)?HTML POST -> 重定向工作,XMLHTTPrequest -> 重定向不起作用(不能从 null 发出任何请求)?
【发布时间】:2013-08-23 13:36:00
【问题描述】:

我有一个有效的 HTML POST 表单要上传到 Amazon S3:

<form action="https://bucketcwav.s3.amazonaws.com/" method="post" enctype="multipart/form-data">
  <input id="s3Name" type="hidden" name="key" value="images/${filename}">
  <input type="hidden" name="AWSAccessKeyId" value="%accesskey%">
  <input type="hidden" name="acl" value="public-read">
  <input type="hidden" name="success_action_redirect" value="http://www.mydomain.com/PHP/imageloadsuccess.php">
  <input type="hidden" name="policy" value="%policy%" />
  <input type="hidden" name="signature" value="%signature%" />
  <input id="mimetype" type="hidden" name="Content-Type" value="image/jpeg">
  <!-- Include any additional input fields here -->

  File to upload to S3: 
  <input id="fileinput" name="file" type="file" accept="image/*">
  <br> 
  <input type="submit" value="Upload File to S3"> 
</form> 

上传成功后,调用http://www.mydomain.com/PHP/imageloadsuccess.php

现在我尝试将我的代码更改为使用 XMLHTTPRequest,因为我需要调整一些 javascript 图像大小:

<body>
<div class="form" id="form">
      File to upload to S3: 
      <input id="fileinput" name="file" type="file" accept="image/*"><span id="progress"></span>
    </form> 

    </div>
</body>
<script type="text/javascript">
if (window.File && window.FileReader && window.FileList && window.Blob) {
    document.getElementById('fileinput').onchange = function(event){
        var file = event.target.files[0]; // The files selected by the user (as a FileList object entry).
        event.target.files[0] = resizeAndUpload(event.target.files[0]);
        };
} else {
        alert('You are using an outdated browser. To get a better site experience, please update your browser to the latest version.');
}

//from http://www.codeforest.net/html5-image-upload-resize-and-crop
function resizeAndUpload(file) {
var reader = new FileReader();
    reader.onloadend = function() {

    var tempImg = new Image();
    tempImg.src = reader.result;
    tempImg.onload = function() {

        var MAX_WIDTH = 1024;
        var MAX_HEIGHT = 768;
        var tempW = tempImg.width;
        var tempH = tempImg.height;
        if (tempW > tempH) {
            if (tempW > MAX_WIDTH) {
               tempH *= MAX_WIDTH / tempW;
               tempW = MAX_WIDTH;
            }
        } else {
            if (tempH > MAX_HEIGHT) {
               tempW *= MAX_HEIGHT / tempH;
               tempH = MAX_HEIGHT;
            }
        }

        var canvas = document.createElement('canvas');
        canvas.width = tempW;
        canvas.height = tempH;
        var ctx = canvas.getContext("2d");
        ctx.drawImage(this, 0, 0, tempW, tempH);

        // from http://alipman88.github.io/debt/about/index.html
        var dataURL = canvas.toDataURL("image/jpeg", 0.9);
        var blob = dataURItoBlob(dataURL);
        var fd = new FormData();

        fd.append("key", "images/"+Math.floor((Math.random()+1)*1000000000000000)+".jpg");
        fd.append("AWSAccessKeyId", "%Accesskey%");
        fd.append("acl", "public-read");
        fd.append("success_action_redirect", "http://www.mydomain.com/PHP/imageloadsuccess.php");       
        fd.append("policy", "%policy%");
        fd.append("signature", "%signature%");
        fd.append("Content-Type", "image/jpeg");
        fd.append("file", blob);
        var xhr = new XMLHttpRequest();
        xhr.open("POST", "https://%bucket%.s3.amazonaws.com/");
        xhr.send(fd);
      }
   }
   reader.readAsDataURL(file);
}

//helperfunctions
    //from https://gist.github.com/kosso/4246840
    function dataURItoBlob(dataURI) {
        var binary = atob(dataURI.split(',')[1]);
        var array = [];
        for(var i = 0; i < binary.length; i++) {
            array.push(binary.charCodeAt(i));
        }
    return new Blob([new Uint8Array(array)], {type: 'image/jpeg'});
}

// from http://stackoverflow.com/questions/11240127/uploading-image-to-amazon-s3-with-html-javascript-jquery-with-ajax-request-n
function uploadProgress(evt) {
    if (evt.lengthComputable) {
      var percentComplete = Math.round(evt.loaded * 100 / evt.total);
      document.getElementById('progressNumber').innerHTML = percentComplete.toString() + '%';
    }
    else {
      document.getElementById('progressNumber').innerHTML = 'unable to compute';
    }
  }

</script>

上传同样成功,只是 Chrome 给我一个错误

XMLHttpRequest 无法加载 http://www.mydomain.com/PHP/imageloadsuccess.php?bucket=bucket&k…=images%2F1028249253286048.jpg&etag=%226ca24feebab0daf48ffea90d16370868%22。无法从 null 发出任何请求。

在 FF 中,此代码不会给我错误,但也不会加载 imageloadsuccess.php。 我对编程很陌生,所以我可能在这里看不到非常简单的东西,非常感谢任何帮助或替代 POST 方法

更新 1: 也许这与它有关:https://src.chromium.org/viewvc/blink?revision=155002&view=revision

更新 2:Chrome 控制台确实显示原点为空,根据http://www.w3.org/TR/cors/#redirect-steps,这是正确的。但它不应该阻止它。这是更新 1 中描述的错误。但也许有人可以告诉我为什么重定向实际上使用 HTML POST 表单加载到屏幕上,而仅在使用 XMLHTTPrequest 时加载到后台?

On POST: 
Request URL:https://%bucket%.s3.amazonaws.com/
Request Headersview parsed
POST https://%bucket%.s3.amazonaws.com/ HTTP/1.1
Referer: http://%mydomain%.com/test2.html
Origin: http://%mydomain%.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.14 Safari/537.36

REDIRECT:
Request URL:http://www.%mydomain%.com/PHP/imageloadsuccess.php?bucket=%bucket%&key=images%2F1851413185242563.jpg&etag=%226ca24feebab0daf48ffea90d16370868%22
Request Headersview parsed
GET http://www.%mydomain%.com/PHP/imageloadsuccess.php?bucket=%bucket%&key=images%2F1851413185242563.jpg&etag=%226ca24feebab0daf48ffea90d16370868%22 HTTP/1.1
**Origin: null**
Referer: http://%mydomain%.com/test2.html

更新 3: 添加

xhr.onload = function() { console.log(["success", this]) };
xhr.onerror = function() { console.log(["error", this]) };

在 FF 和 Chrome 中显示错误,但两者都实际运行 PHP 文件。所以看起来一切都很好,但我仍然不明白为什么会出现错误。在 iOS6 safari 中,加载轮因为 xhr.send(fd); 而一直旋转。 我的 XMLHTTPrequest 一定有问题,但我不知道是什么问题。很抱歉文字量很大,希望有人看到问题所在。

【问题讨论】:

    标签: javascript amazon-s3 xmlhttprequest


    【解决方案1】:

    我认为重定向被阻止是因为您的 PHP 脚本返回的 CORS 标头(它应该以 Access-Control-Allow-Origin: null 响应)。

    还有一个替代解决方案。您可以在原始 S3 POST 请求中从 success() 处理程序中执行单独的 AJAX 请求,而不是使用重定向通知您的应用程序已上传图像(不要在原始请求中包含 success_action_redirect 字段/如果 S3 响应状态码为 200 或 204,则 POST 请求成功)。

    【讨论】:

    • Access-Control-Allow-Origin: null 添加到 PHP:非常适合重定向部分,但不知道需要这样做。然而,在使用 success_action_redirect 时,初始 POST 请求仍然表现得很奇怪:Chrome 将 POST 请求显示为“已取消”,并且 iOS6 Safari 认为该请求永远不会完成(加载轮一直在旋转)。 FF 处理得很好。因此,我尝试了您提到的"success_action_status" = "200",而不是success_action_redirect,并在xhr.onload() 上使用单独的AJAX 请求,它就像一个魅力!非常感谢,我已经用了好几天了。
    猜你喜欢
    • 2012-04-24
    • 1970-01-01
    • 1970-01-01
    • 2019-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-07
    • 1970-01-01
    相关资源
    最近更新 更多