【问题标题】:Header Issue with S3 PUT CommandS3 PUT 命令的标头问题
【发布时间】:2018-08-11 06:49:09
【问题描述】:

我正在尝试使用DropzoneJS 将无服务器上传到 S3。我特别遇到了 AWS Presigned URL 的问题,它表明 x-amz-acl 标头未签名。

Javascript:

var dz = new Dropzone("div#upload", {
  url: "tbd",
  paramName: "file", // The name that will be used to transfer the file
  maxFilesize: 2, // MB
  accept: this.getUploadUrl,
  method: 'put',
  sending: function(file, xhr) {
    var _send = xhr.send;
      xhr.setRequestHeader('x-amz-acl', 'public-read');
      xhr.send = function() {
        _send.call(xhr, file);
      }
    },
});

dz.on('processing', function(file) {
  // change url before sending
  this.options.url = file.uploadUrl;
});

function getUploadUrl(file, cb) {
  var params = {
    fileName: file.name,
    fileType: file.type,
  };
  $.getJSON('signput.php', params).done(function(data) {
    var decodedUri = decodeURIComponent(data['signedRequest']);
    if (!data.signedRequest) {
      return cb('Failed to receive an upload url');
    }

    console.log(decodedUri);
    file.uploadUrl = decodedUri;
    cb();
  }).fail(function() {
    return cb('Failed to receive an upload url');
  });
}

PHP(调用以获取预签名的 url):

$fileName = $_GET['fileName'];

$s3Client = new Aws\S3\S3Client([
'version'     => '2006-03-01',
'region'      => 'us-west-2',
'credentials' => [
    'key'    => '__MY__KEY__',
    'secret' => '__MY__SECRET__',
],]);

$cmd = $s3Client->getCommand('PutObject', [
    'Bucket' => '__MY__BUCKET__',
    'Key'    => $fileName
]);

$request = $s3Client->createPresignedRequest($cmd, '+20 minutes');

// Get the actual presigned-url
$url = (string) $request->getUri();

$urlArray['signedRequest'] = $url;
$urlArray = json_encode($urlArray);
echo $urlArray;

我还尝试在 Dropzone 标头和 S3 getCommand 中将 x-amz-acl 设置为 public-read,但它不起作用。

我得到的错误:

<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code>
<Message>There were headers present in the request which were not signed</Message>
<HeadersNotSigned>x-amz-acl</HeadersNotSigned>
</Error>

【问题讨论】:

  • 试试$cmd = $s3Client-&gt;getCommand('PutObject', [ 'Bucket' =&gt; '__MY__BUCKET__', 'Key' =&gt; $fileName, 'ACL' =&gt; 'public-read' ]);
  • @Michael-sqlbot 不走运:(
  • 我也试过 ACL、AMZ-ACL 和 X-AMZ-ACL
  • 再具体点?
  • 是的,它肯定会让事情变得更清晰 - 你的链接帮助我缩小了范围,再次感谢,我将来会使用它!真的很感激。

标签: php amazon-s3 aws-sdk dropzone.js


【解决方案1】:

有一个问题 - 我需要将 ACL =&gt; 'public-read' 从 JS 代码移动到签名请求中。

Dropzone发送功能变成这样:

sending: function(file, xhr) {
    var _send = xhr.send;
    xhr.send = function() {
      _send.call(xhr, file);
    }
  }

PHP 签名请求变成:

$cmd = $s3Client->getCommand('PutObject', [
  'Bucket' => '__MY__BUCKET__',
  'Key'    => $fileName,
  'ACL'   => 'public-read'
]);

感谢迈克尔为我指明了正确的方向。

最终代码供参考...

Javascript:

var dz = new Dropzone("div#upload", {
  url: "tbd",
  paramName: "file", // The name that will be used to transfer the file
  maxFilesize: 2, // MB
  accept: this.getUploadUrl,
  method: 'put',
  sending: function(file, xhr) {
      var _send = xhr.send;
      xhr.send = function() {
        _send.call(xhr, file);
      }
    },
});

dz.on('processing', function(file) {
  // change url before sending
  this.options.url = file.uploadUrl;
});

function getUploadUrl(file, cb) {
  var params = {
    fileName: file.name,
    fileType: file.type,
  };
  $.getJSON('signput.php', params).done(function(data) {
    var decodedUri = decodeURIComponent(data['signedRequest']);
    if (!data.signedRequest) {
      return cb('Failed to receive an upload url');
    }

    file.uploadUrl = decodedUri;
    cb();
  }).fail(function() {
    return cb('Failed to receive an upload url');
  });
}

PHP:

$fileName = $_GET['fileName'];

$s3Client = new Aws\S3\S3Client([
'version'     => '2006-03-01',
'region'      => 'us-west-2',
'credentials' => [
    'key'    => '__MY_KEY__',
    'secret' => '__MY_SECRET__,
],]);


$cmd = $s3Client->getCommand('PutObject', [
  'Bucket' => '__MY_BUCKET__',
  'Key'    => $fileName,
  'ACL'   => 'public-read'
]);

$request = $s3Client->createPresignedRequest($cmd, '+20 minutes');

// Get the actual presigned-url
$url = (string) $request->getUri();

$urlArray['signedRequest'] = $url;
$urlArray = json_encode($urlArray);
echo $urlArray;

【讨论】:

    猜你喜欢
    • 2017-08-13
    • 2021-04-10
    • 2021-01-11
    • 2021-07-21
    • 1970-01-01
    • 2013-08-31
    • 1970-01-01
    • 2021-07-11
    • 2021-11-30
    相关资源
    最近更新 更多