我创建了一个API,该API为我的私有s3存储桶中的文件生成一个预签名的url。我想将这些URL存储到一个数组中,以便可以从另一个应用程序中调用它们。 [“ FILE1预签名的url”,“ FILE2预签名的url”等。]但是,我对API如何读取命令的方式感到困惑,因此来到这里寻求帮助。


输入时,为什么承载API的页面没有显示填充的数组?直到我刷新页面后,它才最终填充数组。


我希望每次重置数组并替换链接,而不是添加到数组末尾。我还需要数组在页面加载后立即显示,而不是刷新它以查看结果。

当我进入提供API的页面时,将显示以下内容:
javascript - 使用API​​生成多个预签名的URL-LMLPHP

当我点击刷新时,该数组将填充预签名的网址:

["https://bucketname.s3.amazonaws.com/file1.pdf?AWSAccessKeyId=ACCESSKEY&Expires=1572669513&Signature=SIGNATURE","https://bucketname.s3.amazonaws.com/file2.pdf?AWSAccessKeyId=ACCESSKEY&Expires=1572669513&Signature=SIGNATURE"]


但是,当我再次刷新页面时,它再次将这两个文件压入数组中,而不是两个。如果我不断刷新页面,它将继续添加另外两个URL,依此类推。 (如果循环停在两个不同的时间,为什么要这样做)

const express = require('express');
const bodyParser = require('body-parser');
const morgan = require('morgan');
const uuid = require('uuid');
const AWS = require('aws-sdk');
let config = require('./config');

var s3 = new AWS.S3();
s3.config.update({
    accessKeyId: config.accessKeyId,
    secretAccessKey: config.secretAccessKey,
    region: 'us-east-1'
});

var app = express();
var router = express.Router();

// Create an array that houses pre-signed Urls


// Loop through x amt of times (depending on number of documents)
// Push each url into an array called 'preSignedUrls'
// Exit loop and reset array to re-generate new urls
let preSignedUrls = [];
    function getSignedURL(req, res, next) {
    Key = ['file1.pdf', 'file2.pdf']
        for ( i = 0; i < Key.length; i++ ){
            var params = {
                Bucket: 'bucketName',
                Key: Key[i],
                Expires: 36000
            };
                console.log(Key.length);
                console.log(i);
                s3.getSignedUrl('getObject', params, function(err, signedURL) {
                    if (err) {
                        console.log(err);
                        return next(err);
                    } else {
                        console.log(signedURL);
                        console.log(params);
                        preSignedUrls.push(signedURL);
                    }
                });
        }
        res.json(preSignedUrls);

    }
router.route('/get_signed_url')
    .get(getSignedURL);

app.use(morgan('combined'));
app.use(bodyParser.json());
app.use('/v1', router);

var PORT = process.env.PORT || 3001;
var HOST = process.env.HOST || '10.123.456.789';

console.log("Listening on", HOST, PORT);
app.listen(PORT, HOST);


这是来自node.js终端的输出(也就是我放入代码中的日志命令以测试输出)

2
0
2
1
https://bucketname.s3.amazonaws.com/file1.pdf?AWSAccessKeyId=ACCESSKEY&Expires=1572669520&Signature=SIGNATURE
{ Bucket: 'bucketname',
  Key: 'file2.pdf',
  Expires: 36000 }
https://bucketname.s3.amazonaws.com/file2.pdf?AWSAccessKeyId=ACCESSKEY&Expires=1572669520&Signature=SIGNATURE
{ Bucket: 'bucketname',
  Key: 'file2.pdf',
  Expires: 36000 }


我对此感到奇怪的是,它将对象参数记录为file2.pdf,但它输出的预签名URL按应有的顺序显示了file1.pdf和file2.pdf。另外,由于我认为for循环按顺序执行命令,因此在对象之前显示长度和变量i的事实使我感到困惑。

最佳答案

因为signedURL是来自s3.getSignedUrl()的响应。它是异步运行的,并且具有自己的值和上下文。
但是另一方面,变量参数将返回for循环的最后一个值。这是因为函数s3.getSignedUrl尚未执行,并且for循环较早执行。 for循环不等待s3.getSignedUrl()异步完成。
如果要保留i值,则可能希望使用箭头功能。

这是其他线程执行此操作的一种方法。
async / await looping through array of to get s3 signed URL's

08-16 06:37