Jquery getSignedUrl不允许从浏览器上载

Jquery getSignedUrl不允许从浏览器上载,jquery,node.js,ajax,amazon-web-services,amazon-s3,Jquery,Node.js,Ajax,Amazon Web Services,Amazon S3,几天来,我一直在尝试直接从浏览器上传s3 我使用jqueryajax请求来查询我的服务器,以获得已签名的url(以确保用户经过身份验证)。 然后,我返回已签名的url,并使用另一个jQueryAjax调用尝试上载该文件 My backend node.js代码: exports.getSignedUrl = async (key, content) => { try { if (!key){ return Promise.reject('No key sup

几天来,我一直在尝试直接从浏览器上传s3

我使用jqueryajax请求来查询我的服务器,以获得已签名的url(以确保用户经过身份验证)。 然后,我返回已签名的url,并使用另一个jQueryAjax调用尝试上载该文件

My backend node.js代码:

exports.getSignedUrl = async (key, content) => {
  
  try {

    if (!key){
      return Promise.reject('No key supplied');
    }
    if (!content){
      return Promise.reject('No content type supplied');
    }
    
    const s3 = new AWS.S3({
      region: 'eu-west-1',
      signatureVersion: 'v4'
    });
    let params = {
      Bucket: siteSettings.s3Bucket, 
      Key: key,
      ContentType: content,
      Expires: process.env.S3_UPLOAD_TIME || 240
    };
  
    let url = await s3.getSignedUrl('putObject', params);
  
    return Promise.resolve(url);

  } catch (error) {
    return Promise.reject(error);
  }

}
传递的
params
变量包含:

{
    Bucket:"[bucketname]"
    ContentType:"image/jpeg"
    Key:"ctl/5f43d07cbeb97850f4fa5246-small.jpg"
}
这将生成一个URL,如:

https://[bucketname].s3.eu-west-1.amazonaws.com/ctl/5f43d07cbeb97850f4fa5246-small.jpg?Content-Type=image%2Fjpeg&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAXBXXXXXXXXXXBWVG%2F20200923%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Date=20200923T101959Z&X-Amz-Expires=900&X-Amz-Signature=474415e11b9eec7636ab8a1995a28f92cebab18949fb981d37b6c6772209f039&X-Amz-SignedHeaders=host
我的浏览器代码:

const getActiveS3SignedUri = (filename, content, callback) => {

  $.ajax({
    method: 'POST', 
    url: baseUrl + '/aws/getsignedurl',
    data: {
      filename: filename,
      content: content
    },
    dataType: 'json',
    complete: (data) => {
      if (data.responseJSON && data.responseJSON.success==true){
        callback(null, data.responseJSON);
      } else {
        if (data.responseJSON.err || data.responseJSON.error){
          callback(data.responseJSON.err || data.responseJSON.error);
        } else {
          callback(`Couldn't get URL, unknown error`);
        }
      }
    }
  })
}

const uploadToS3 = (url, fileObject, callback) => {

  let file = document.getElementById(fileObject).files[0];

  $.ajax({
    method: 'POST', // I have tried both POST and PUT here
    headers: {"Content-Type": file.type},
    processData: false,
    url: url,
    data: file,
    complete: (data) => {
      callback(null, data);
    }
  })
}

$(() => {

  $('#summernote').summernote({
    callbacks: {
      onImageUpload: function(files) {
        // upload image to S3 server and create imgNode...
        
        $summernote.summernote('insertNode', imgNode);
      }
    }
  });

  $('#validate-target').on('submit', (e) => {

      //- let input = $('#input_dummy');
      //- let val = $('#input_quill > .ql-editor');
      //- input.val(val.html());

  });

  $('#summernote-input').on('change', (e) => {
    let fileInput = $(e.target);
    let file = fileInput[0].files[0];

    getActiveS3SignedUri(file.name, file.type, (err, response) => {
      if (!err){
        uploadToS3(response.url, 'summernote-input', (err, data) => {
          alert(JSON.stringify(data));
        });
      }
    })
  });
这是将以下内容发布到AWS url:

Host: [bucketname].s3.eu-west-1.amazonaws.com
Connection: keep-alive
Content-Length: 12147
Accept: */*
DNT: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
Content-Type: image/jpeg
Origin: http://localhost:3000
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://localhost:3000/admin/settings/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,en-GB;q=0.8
使用请求有效负载:

我经常遇到以下错误:

<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message><AWSAccessKeyId>AKIAXBXXXXXXXXXXBWVG</AWSAccessKeyId><StringToSign>AWS4-HMAC-SHA256
20200923T102902Z
20200923/eu-west-1/s3/aws4_request
9d9d71f4434cbbc236336d33db9e377e2c5790e1acb200e35ece8d25bc96c15b</StringToSign><SignatureProvided>41f375741726f222bcb86018ffae317f9e2a58891105b46783d5f7b343c97352</SignatureProvided><StringToSignBytes>...truncated...</StringToSignBytes><CanonicalRequest>POST
/ctl/5f43d07cbeb97850f4fa5246-small.jpg
Content-Type=image%2Fjpeg&amp;X-Amz-Algorithm=AWS4-HMAC-SHA256&amp;X-Amz-Credential=AKIAXBWXRFJB4RKEBWVG%2F20200923%2Feu-west-1%2Fs3%2Faws4_request&amp;X-Amz-Date=20200923T102902Z&amp;X-Amz-Expires=900&amp;X-Amz-SignedHeaders=host
host:toy-lib-dev-bucket.s3.eu-west-1.amazonaws.com

host
UNSIGNED-PAYLOAD</CanonicalRequest><CanonicalRequestBytes>...truncated...</CanonicalRequestBytes><RequestId>470D4BB6D67CDF82</RequestId><HostId>GmktGQDhTmi5a/26bR82tY/SE0C1DQdSZnGNAyp6VGmpYBoTgKXFuTlAYuZpYVCBgdc1Grck6CE=</HostId></Error>
我的s3 bucket CORS配置为:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <AllowedMethod>PUT</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>

@bendataclear将图像文件转换为blob或base64字符串,然后进行处理。

这是签名不匹配的原因吗?向S3提供base64或blob会改变文件的存储方式吗?我有一个肯定有效的示例:。它与您的用例并不完全匹配,但这可能是一个良好的开端point@TamásSallai使用示例中的浏览器代码和
fetch
而不是
$。ajax
可以工作,但我不明白为什么或者如何工作。可能内容类型标题更改了签名。尝试从ajax请求中删除内容,看看它如何影响发送的HTTP请求(您可以在devtools中检查)
fetch(url, {
  method: "PUT",
  body: file,
});