扩展@semir-deljić 答案。
每次我们调用getSignedUrl
函数时,它都会生成新的 URL。这将导致即使存在Cache Control
标头也不会缓存图像。
因此,我们使用计时器库来冻结时间。现在调用该函数时,它认为时间还没有过去,它返回相同的 URL。
const moment = require('moment');
const tk = require("timekeeper");
function url4download(awsPath, awsKey) {
function getFrozenDate() {
return moment().startOf('week').toDate();
}
// Paramters for getSignedUrl function
const params = {
// Ref: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html
// Ref: https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html
Bucket: awsBucket,
Key: `${awsPath}/${awsKey}`,
// 604800 == 7 days
ResponseCacheControl: `public, max-age=604800, immutable`,
Expires: 604800, // 7 days is max
};
const url = tk.withFreeze(getFrozenDate(), () => {
return S3.getSignedUrl('getObject', params);
});
return url;
}
注意:
使用moment().toDate()
, 作为计时器需要一个本地日期对象。
即使是使用knox
库的问题也很棘手,我的答案是使用 aws 官方库。
// This is how the AWS & S3 is initiliased.
const AWS = require('aws-sdk');
const S3 = new AWS.S3({
accessKeyId: awsAccessId,
secretAccessKey: awsSecretKey,
region: 'ap-south-1',
apiVersion: '2006-03-01',
signatureVersion: 'v4',
});
灵感来源:https ://advancedweb.hu/cacheable-s3-signed-urls/