2014-01-17 5 views
1

저는 http://pjambet.github.io/blog/direct-upload-to-s3/을 자습서로 사용하고 있습니다. 이미 CORS를 사용하도록 설정했습니다 (CORS 파일 참조). 나는 파일 업로드 쿼리의 (추가) 기능인 JSON 응답을 받는다. 실패는 서명과 정책을 얻은 후에 발생합니다. 파일을 실제로 업로드하려고하면 Amazon에서 Access Denied 오류가 발생합니다. 파일이 업로드되지 않습니다. 내가 놓친 게 있니?Amazon 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> 

자바 스크립트 :

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

펄 :

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 Fail 콜백이 계속 작동하는지 확인하십시오. Iframe Transport 관련 문제점에 대해 들어 봤습니다. – Fractaliste

+0

그래, 오류 콜백이 작동하지 않습니다 ... 유효한 업로드 응답을 받았지만 요청이 실패했습니다. 구제에 대한 아이디어가 있습니까? –

1

액세스하려고하는 파일을 S3로 이동 단계에 따라 따라주십시오 단순히 우측 클릭 -> 확인 (가 액세스 할 공공 확인) 공공

이렇게하면 문제가 해결됩니다.

+0

파일 업로드에 실패했습니다. –

관련 문제