3

将文件从strapi上传到s3工作正常。我正在尝试使用签名的 url 来保护文件:

var params = {Bucket:process.env.AWS_BUCKET, Key: `${path}${file.hash}${file.ext}`, Expires: 3000};
      var secretUrl = ''
      S3.getSignedUrl('getObject', params, function (err, url) {
        console.log('Signed URL: ' + url);
        secretUrl = url
      });

      
      S3.upload(
        {
          Key: `${path}${file.hash}${file.ext}`,
          Body: Buffer.from(file.buffer, 'binary'),
          //ACL: 'public-read',
          ContentType: file.mime,
          ...customParams,
        },
        (err, data) => {
          if (err) {
            return reject(err);
          }

          // set the bucket file url
          //file.url = data.Location;
          file.url = secretUrl;
          console.log('FIle URL: ' + file.url);

          resolve();
        }
      );

file.url (secretUrl) 包含正确的 URL,我可以在浏览器中使用它来检索文件。但是,无论何时阅读文件形式的strapi 管理面板,都不会显示文件或缩略图。我发现strapi向文件中添加了一个参数,例如?2304.4005,它破坏了AWS的文件获取。我在哪里以及如何改变这种行为

帮助表示赞赏

4

2 回答 2

2

似乎虽然覆盖控制器和集合模型的生命周期以及strapi-plugin-content-manager 以考虑S3签名的url,但其中一个Strapi UI组件?123.123向从接收到的实际url添加了一个奇怪的钩子/引用后端,在There were headers present in the request which were not signed尝试从 CMS UI 中查看图像时导致 AWS 出现以下错误。

带有故障组件的屏幕截图

在挖掘了 Strapi 使用的代码和 node_modules 之后,您似乎会在其中找到以下内容strapi-plugin-upload/admin/src/components/CardPreview/index.js


return (
 <Wrapper>
   {isVideo ? (
     <VideoPreview src={url} previewUrl={previewUrl} hasIcon={hasIcon} />
   ) : (
     // Adding performance.now forces the browser no to cache the img
     // https://stackoverflow.com/questions/126772/how-to-force-a-web-browser-not-to-cache-images
     <Image src={`${url}${withFileCaching ? `?${cacheRef.current}` : ''}`} />
   )}
 </Wrapper>
);
};

CardPreview.defaultProps = {
extension: null,
hasError: false,
hasIcon: false,
previewUrl: null,
url: null,
type: '',
withFileCaching: true,
};

对于 withFileCaching,默认设置为 true,因此会将const cacheRef = useRef(performance.now());查询参数附加到 url 以避免浏览器缓存。

通过将其设置为 false,或者离开<Image src={url} />应该可以解决额外查询参数的问题,并允许您也可以从 Strapi UI 使用 S3 签名 URL 预览。

这也将转化为使用文档https://strapi.io/documentation/developer-docs/latest/development/plugin-customization.htmlstrapi-plugin-upload您的/extensions/strapi-plugin-upload/...

于 2021-04-12T14:23:47.907 回答
0

这是我创建签名 URL 以保护您的资产的解决方案。该 URL 将在一定时间内有效。

  1. 使用要保护的媒体字段创建集合类型。在我的示例中,集合类型被调用invoice,媒体字段被调用document

  2. 创建 S3 存储桶

  3. 安装和配置strapi-provider-upload-aws-s3适用于 JavaScript 的 AWS 开发工具包

  4. 为您的发票端点自定义 Strapi 控制器findOne(在此示例中,我使用核心控制器)

const { sanitizeEntity } = require('strapi-utils');
var S3 = require('aws-sdk/clients/s3');

module.exports = {

  async findOne(ctx) {
    const { id } = ctx.params;

    const entity = await strapi.services.invoice.findOne({ id });
    // key is hashed name + file extension of your entity
    const key = entity.document.hash + entity.document.ext;

    // create signed url
    const s3 = new S3({
        endpoint: 's3.eu-central-1.amazonaws.com',   // s3.region.amazonaws.com
        accessKeyId: '...',       // your accessKeyId
        secretAccessKey: '...',   // your secretAccessKey
        Bucket: '...',         // your bucket name
        signatureVersion: 'v4',
        region: 'eu-central-1'           // your region
    });

    var params = {
        Bucket:'',   // your bucket name
        Key: key, 
        Expires: 20 // expires in 20 seconds
    };

    var url = s3.getSignedUrl('getObject', params);

    entity.document.url = url  // overwrite the url with signed url

    return sanitizeEntity(entity, { model: strapi.models.invoice });
  },

};
于 2021-03-03T13:38:37.310 回答