Асинхронная загрузка (HTTP POST) в Amazon S3: почему я не получаю правильные обратные вызовы? - PullRequest
4 голосов
/ 23 февраля 2011

Я пытаюсь загрузить файл асинхронно, используя HTTP POST и jQuery, но у меня возникает странная проблема: я не могу получить правильный обратный вызов для запуска.Когда я загружаю файл, он возвращает состояние «ОК» с кодом 201 , и я могу получить доступ к файлу в моем S3-контейнере , но jQuery запускает функцию «error» обратного вызова каждый раз .Осмотрев объект XHR чуть дальше, я наткнулся на:

Error: Permission denied for [http://192.168.2.247] to get property Window.document from [https://pentoolcn.aplusldesign.com.s3.amazonaws.com].

Что может быть причиной этого?Этот код взят почти дословно из http://developer.amazonwebservices.com/connect/entry!default.jspa?categoryID=139&externalID=1434&fromSearchPage=true и синхронно (обычная отправка формы и обновление страницы), он работал отлично.

Мой код ниже.

<?php
// CDN service options are Amazon S3 "S3" or None "none" [default]
$CDN_SERVICE_TYPE = "S3";
$CDN_SERVICE_TYPE = 'none';
$CDN_ACCESS_KEY = '[CONFIDENTIAL]';
$CDN_SECRET_KEY = '[CONFIDENTIAL]';
$CDN_BUCKET = '[CONFIDENTIAL]';
$CDN_FOLDER = '[CONFIDENTIAL]'; // folder within bucket
$CDN_ACL = 'public-read';
$CDN_MAX_FILE_SIZE = 20 * 1048576; // MB size limit
$SUCCESS_REDIRECT = 'http://' . $_SERVER['SERVER_NAME'] . ($_SERVER['SERVER_PORT']=='' ? '' : ':') .
                        $_SERVER['SERVER_PORT'] . '/' . 'index.php'/*$_SERVER['SERVER_SELF']*/ .
                        '?ok' ; // SendFileS3.php is URL from server root

// process result from transfer, if query string present
$query = $_SERVER['QUERY_STRING'];

// setup transfer form
$expTime = time() + (1 * 60 * 60); // now plus one hour (1 hour; 60 mins; 60secs)
$expTimeStr = gmdate('Y-m-d\TH:i:s\Z', $expTime);
//echo 'expTimeStr: '. $expTimeStr ."<BR/>";
//echo 'SUCCESS_REDIRECT: '. $SUCCESS_REDIRECT ."<BR/>";

// create policy document
$policyDoc = '
{"expiration": "' . $expTimeStr . '",
    "conditions": [
        {"acl": "' . $CDN_ACL . '"},
        {"bucket": "' . $CDN_BUCKET . '"},
        {"success_action_status": "201"},
        ["starts-with", "$key", "' . $CDN_FOLDER . '"],
        [\'starts-with\', \'$folder\',\'\'],
        [\'starts-with\', \'$filename\', \'\'],
        [\'starts-with\',\'Upload\', \'\'],
        ["content-length-range", 0, ' . $CDN_MAX_FILE_SIZE . '],
    ]
}
';
//
// Removed the success_action_redirect cause Flash doesn't like it
$policyDocFlash = '
{"expiration": "' . $expTimeStr . '",
    "conditions": [
        {"acl": "' . $CDN_ACL . '"},
        {"bucket": "' . $CDN_BUCKET . '"},
        {"success_action_status": "201"},
        ["starts-with", "$key", "' . $CDN_FOLDER . '"],
        [\'starts-with\', \'$folder\',\'\'],
        [\'starts-with\', \'$filename\', \'\'],
        [\'starts-with\',\'Upload\', \'\'],
        ["content-length-range", 0, ' . $CDN_MAX_FILE_SIZE . ']
    ]
}
';


//echo "policyDoc: " . $policyDoc . '<BR/>';
// remove CRLFs from policy document
$policyDoc = implode(explode('\r', $policyDoc));
$policyDoc = implode(explode('\n', $policyDoc));
$policyDoc64 = base64_encode($policyDoc); // encode to base 64
// create policy document signature
$sigPolicyDoc = base64_encode(hash_hmac("sha1", $policyDoc64, $CDN_SECRET_KEY, TRUE/*raw_output*/));


//echo "policyDoc: " . $policyDoc . '<BR/>';
// remove CRLFs from policy document
$policyDocFlash = implode(explode('\r', $policyDocFlash));
$policyDocFlash = implode(explode('\n', $policyDocFlash));
$policyDoc64Flash = base64_encode($policyDocFlash); // encode to base 64
// create policy document signature
$sigPolicyDocFlash = base64_encode(hash_hmac("sha1", $policyDoc64Flash, $CDN_SECRET_KEY, TRUE/*raw_output*/)); 
?>
<html>
<head>
    <title>S3 POST Form</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <link rel="stylesheet" href="css/uploadify.css" type="text/css" />
    <script type="text/javascript" src="js/jquery-1.3.2.min.js"></script>
    <script type="text/javascript" src="js/jquery.uploadify.v2.1.4.min.js"></script>
    <script type="text/javascript" src="js/swfobject.js"></script>
    <script src="js/jquery.form.js" type="text/javascript" charset="utf-8"></script>
    <script src="js/jquery.validate.min.js" type="text/javascript" charset="utf-8"></script>

    <script type="text/javascript">
        function setType(){
            document.getElementById("Content-Type").value = getMIMEtype(document.getElementById("file").value);
        }

        var CDN_BUCKET = "<?php echo($CDN_BUCKET); ?>";

        $(document).ready(function() {      
            $("#remote-form").submit(function() {
                console.log("Submitting...");

                $(this).ajaxSubmit({
                    url:        "https://"+CDN_BUCKET+".s3.amazonaws.com/",
                    target:     '#response',
                    success: function(response, status, xhr) {
                        console.info("Success!");
                    },
                    error: function(xhr, status, error) {
                        console.error("Failure.");
                    },
                    completed: function(xhr, status) {
                        console.log("Done.");
                    }
                });

                return false
            });
        });
    </script>

</head>

<body>
    <div id="response" style="border: 1px solid black"></div>
    <?php
        $res = explode('&', $query);
        foreach($res as $ss) {
            //echo 'ss: ' . $ss . '<BR/>';
            if(substr($ss,0,7) == 'bucket=') $qBucket = urldecode(substr($ss,7));
            if(substr($ss,0,4) == 'key=') $qKey = urldecode(substr($ss,4));
        }
        if($qBucket != '') {
            // show transfer results
            echo 'File transferred: ' . $qBucket . '/' . $qKey . '<BR/><BR/>';
            $expires = time() + 1*24*60*60/*$expires*/;
            $resource = $qBucket."/".urlencode($qKey);
            $stringToSign = "GET\n\n\n$expires\n/$resource";
            //echo "stringToSign: $stringToSign<BR/><BR/>";
            $signature = urlencode(base64_encode(hash_hmac("sha1", $stringToSign, $CDN_SECRET_KEY, TRUE/*raw_output*/)));
            //echo "signature: $signature<BR/><BR/>";
            $queryString = "<a href='http://s3.amazonaws.com/$resource?AWSAccessKeyId=$CDN_ACCESS_KEY&Expires=$expires&Signature=$signature'>$bucket/$key</a>";

            echo "URL (private read): $queryString<BR/><BR/>";
            echo 'URL (public read) : http://s3.amazonaws.com/' . $qBucket . '/' . $qKey . '<BR/><BR/>';
        }
    ?>
    <form id="remote-form" method="post" action="?" enctype="multipart/form-data">
        <!-- amazon configuration -->
        <input type="hidden" name="key" value="<?php echo($CDN_FOLDER.'${filename}'); ?>" />
        <input type="hidden" name="AWSAccessKeyId" value="<?php echo($CDN_ACCESS_KEY); ?>" />
        <input type="hidden" name="acl" value="<?php echo($CDN_ACL); ?>" />
        <input type="hidden" name="success_action_status" value="201" />
        <input type="hidden" name="policy" value="<?php echo($policyDoc64); ?>" />
        <input type="hidden" name="signature" value="<?php echo($sigPolicyDoc); ?>" />
        <input type="hidden" name="folder" value="" />
        <input type="hidden" name="Filename" value="" />
        <!-- file data -->
        File to upload to S3:
        <input name="file" id="file_upload" type="file">
        <br/><br/> 
        <input type="submit" value="Upload File to S3">
    </form>
</body>
</html>

Ответы [ 3 ]

2 голосов
/ 23 марта 2011

Я бы порекомендовал создать невидимый iframe и отправить через него вашу форму.Таким образом, нарушение политики XHR с тем же происхождением не будет проблемой.

2 голосов
/ 17 марта 2011

После проверки объекта XHR

Эта ошибка для меня выглядит как нарушение политики одного и того же происхождения. Вы можете сделать отправку формы в другой домен, но вы не можете сделать XHR ни с чем, кроме хоста, с которого пришел ваш JS, и я не вижу XHR в образце, который вы связали.

0 голосов
/ 16 июня 2013

Теперь это можно установить с помощью CORS.Проверить http://docs.aws.amazon.com/AmazonS3/latest/dev/cors.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...