簡體   English   中英

如何在 Heroku 上為 AWS S3 正確設置簽名的 url 上傳?

[英]How to correctly setup signed url uploads for AWS S3 on Heroku?

問題

我有一個在 Heroku 上運行的簡單應用程序,用戶可以在其中上傳和查看圖像/視頻。 我正在嘗試使用簽名網址。 我試過這個教程和這個教程。 事實上,我克隆了 Github 存儲庫。 問題是當我嘗試上傳圖像時,我會收到以下錯誤:

[錯誤] 預檢響應不成功

[錯誤] 由於訪問控制檢查,XMLHttpRequest 無法加載(長鏈接)。

[錯誤] 加載資源失敗:預檢響應不成功(img.jp2,第 0 行)

具體問題

我認為問題可能出在 S3 存儲桶設置上,因為我對 AWS 沒有太多經驗。 所以我的問題是是什么導致了這個問題,我該如何解決?

這是我的 COR 配置

<?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>
    <AllowedMethod>HEAD</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>

這是生成預簽名網址的代碼

aws.config.region = 'us-west-1';
BUCKET = process.env.S3_BUCKET;

app.get('/account', (req, res) => res.render('account.html'));

app.get('/sign-s3', (req, res) => {
  const s3 = new aws.S3();
  const fileName = req.query['file-name'];
  const fileType = req.query['file-type'];
  const s3Params = {
    Bucket: S3_BUCKET,
    Key: fileName,
    Expires: 60,
    ContentType: fileType,
    ACL: 'public-read'
  };

  s3.getSignedUrl('putObject', s3Params, (err, data) => {
    if(err){
      console.log(err);
      return res.end();
    }
    const returnData = {
      signedRequest: data,
      url: `https://${S3_BUCKET}.s3.amazonaws.com/${fileName}`
    };
    res.write(JSON.stringify(returnData));
    res.end();
  });
});

這是嘗試上傳到 S3 的代碼

function uploadFile(file, signedRequest, url){
  const xhr = new XMLHttpRequest();
  xhr.open('PUT', signedRequest);
  xhr.onreadystatechange = () => {
    if(xhr.readyState === 4){
      if(xhr.status === 200){
        alert('success')
      }
      else{
        alert('Could not upload file.');
      }
    }
  };
  xhr.send(file);
}

嘗試了什么

添加

<AllowedMethod>OPTIONS</AllowedMethod>

結果是

Found unsupported HTTP method in CORS config. Unsupported method is OPTIONS

補充說明

我試過 chrome 和 safari。 原來我不小心默認使用

 <AllowedHeader>authorization</AllowedHeader>

把這個改回

 <AllowedHeader>*</AllowedHeader>

結果是:

[Long link] Failed to load resource: the server responded with a status of 403 (Forbidden)

我想我發現了問題,您應該設置content-type因為它也在生成簽名時使用。

xhr.setRequestHeader("Content-Type", "application/octet-stream");

Heroku 教程遺漏了一些細節(或需要更新):

需要更新的配置:

aws.config.region = 'us-west-1';
aws.config.update({
  accessKeyId:  process.env.AWS_ACCESS_KEY_ID,
  secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
})

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM