2014-01-17 146 views
1

我使用http://pjambet.github.io/blog/direct-upload-to-s3/作爲教程。我已經啓用了CORS(請參閱CORS文件)。我得到了JSON響應,這在文件上傳查詢中沒有問題(在添加中)。獲得簽名和政策後發生故障。嘗試實際上傳文件時,我收到來自亞馬遜的「拒絕訪問」錯誤。該文件不會上傳。我錯過了什麼嗎?直接訪問亞馬遜S3訪問被拒絕

HTML:

<form class="file_upload" action="https://<% $AWSBUCKET %>.s3.amazonaws.com" method="post" enctype="multipart/form-data"> 
<input type="hidden" name="key" /> 
<input type="hidden" name="policy" /> 
<input type="hidden" name="signature" /> 
<input type="hidden" name="AWSAccessKeyId" value="<% $AWSACCESS %>" /> 
<input type="hidden" name="acl" value="public-read" /> 
<input type="hidden" name="success_action_status" value="201" /> 

<div class="fileupload-content"> 
    <div class="fileupload-progress"> 
    </div> 
</div> 
<div class="file-upload"> 
    <span class="btn btn-success fileinput-button"> 
    <i class="glyphicon glyphicon-plus"></i> 
    <span>Select files...</span> 
    <input type="file" name="file" multiple> 
    </span> 
    <div class="progress progress-striped active"> 
    <div class="bar"> 
    </div> 
</div> 

的Javascript:

$(function() { 
    $('.file_upload').each(function() { 
    var form = $(this) 
    $(this).fileupload({ 
     url: form.attr('action'), 
     type: 'POST', 
     autoUpload: true, 
     dataType: 'xml', // This is really important as s3 gives us back the url of the file in a XML document 
     add: function (event, data) { 
     $.ajax({ 
      url: "s3signed.html", 
      type: 'GET', 
      dataType: 'json', 
      data: {filename: data.files[0].name, max_file_size : <% $MAX_FILE_SIZE %>}, // send the file name to the server so it can generate the key param 
      async: false, 
      success: function(data) { 
      // Now that we have our data, we update the form so it contains all 
      // the needed data to sign the request 
      form.find('input[name=key]').val(data.key) 
      form.find('input[name=policy]').val(data.policy) 
      form.find('input[name=signature]').val(data.signature) 
      console.log(data.key); 
      console.log(data.policy); 
      console.log(data.signature); 
      } 
     }) 
     data.submit(); 
     }, 
     send: function(e, data) { 
     $('.progress').fadeIn(); 
     }, 
     progress: function(e, data){ 
     // This is what makes everything really cool, thanks to that callback 
     // you can now update the progress bar based on the upload progress 
     var percent = Math.round((e.loaded/e.total) * 100) 
     $('.bar').css('width', percent + '%') 
     }, 
     fail: function(e, data) { 
     console.log('fail'); 
     console.log(data); 
     console.log(e); 
     }, 
     success: function(data) { 
     // Here we get the file url on s3 in an xml doc 
     var url = $(data).find('Location').text() 

     $('#real_file_url').val(url) // Update the real input in the other form 
     }, 
     done: function (event, data) { 
     $('.progress').fadeOut(300, function() { 
      $('.bar').css('width', 0) 
     }) 
     }, 
    }) 
    }) 
}); 

的Perl:

use Digest::HMAC_SHA1 qw(hmac_sha1 hmac_sha1_hex); 
use MIME::Base64; 

use Data::Uniqid qw (uniqid); 
my $uniqid = uniqid; 

my $key = "upload/$uniqid/$filename"; 
my $policy = s3PolicyDocument($AWSBUCKET, $max_file_size, $key); 
my $signature = s3Signature($AWSSECRET, $policy); 

my %response = (
    policy => $policy, 
    signature => $signature, 
    key => $key, 
    success_action_status => 201 
); 

use JSON; 
print JSON::encode_json(\%response); 

sub s3PolicyDocument { 
    my ($AWSBUCKET, $max_file_size, $key) = @_; 
    use DateTime; 
    my $dt = DateTime->now; 
    $dt->add(minutes => 30); 

    my $policy = '{"expiration": "'.$dt.'", 
    "conditions": [ 
     {"bucket": "'.$AWSBUCKET.'"}, 
     {"acl": "public-read"}, 
     ["starts-with", "$key", ""], 
     ["starts-with", "$Content-Type", ""], 
     ["starts-with", "$name", ""], 
     ["starts-with", "$Filename", ""], 
     ["content-length-range", 0, '.$max_file_size.'], 
     {"success_action_status": "201"}, 
    ] 
    }'; 

    use Digest::HMAC_SHA1 qw(hmac_sha1 hmac_sha1_hex); 
    use MIME::Base64; 


    $policy = encode_base64($policy); 
    $policy =~ s/\n//g; 
    return $policy; 
} 

sub s3Signature { 
    my($AWSSECRET, $policy) = @_; 
    my $signature = encode_base64(hmac_sha1($policy, $AWSSECRET)); 
    $signature =~ s/\n//g; 
    return $signature; 
} 

CORS:

<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> 
    <CORSRule> 
     <AllowedOrigin>*</AllowedOrigin> 
     <AllowedMethod>GET</AllowedMethod> 
     <AllowedMethod>POST</AllowedMethod> 
     <AllowedMethod>PUT</AllowedMethod> 
     <AllowedHeader>*</AllowedHeader> 
    </CORSRule> 
</CORSConfiguration> 

亞馬遜響應:

<Error> 
<Code>AccessDenied</Code> 
<Message>Access Denied</Message> 
<RequestId>2448EA4E8E1F5377</RequestId> 
<HostId>NlbqOAnjhPnqQLpaJRY1cVC6nFJ3ziVK+7ENrgILhA2njekXnp4mowv7jyTE2Z7K</HostId> 
</Error> 

回答

2

根據跨站點上載的文檔,您應該使用forceIframeTransport選項。

$(this).fileupload({ 
    forceIframeTransport : true, 
    ... 
}); 
+0

這樣做!我不得不刪除一些策略參數,但它工作正常! –

+0

@RijviRajib檢查你的失敗回調是否仍然有效,我聽說Iframe Transport有問題。 – Fractaliste

+0

是的,失敗回調不工作...我得到一個有效的上傳響應,但請求失敗。任何補救措施的想法? –

1

請按照下列步驟 進入到S3 您試圖訪問該文件(將其公開訪問) 只需右鍵點擊 - >公佈

這應該可以解決你的問題。

+0

文件上傳失敗。 –