我一直在寻找一种从预签名URL写入S3存储桶中JSON文件的方法。从我的研究看来,这是可以做到的,但是这些不在Node中:
没有从我的搜索中找到节点解决方案,而是使用第三方API,我试图将回调写到S3存储桶中的JSON。我可以毫无问题地生成预签名URL,但是当我尝试将虚拟文本写入预签名URL时,我得到:
错误:ENOENT:没有这样的文件或目录,请打开 'https://path-to-file-with-signed-url'
当我尝试使用writeFile
时:
fs.writeFile(testURL, `This is a write test: ${Date.now()}`, function(err) {
if(err) return err
console.log("File written to")
})
根据我对file
下的documentation的理解,它说我可以使用URL。我开始相信这可能是权限问题,但是我在文档中找不到任何运气。
实现node-fetch
后,仍然会基于预签名URL向S3中的文件写入错误(403 Forbidden
),这是我编写的模块中的完整代码:>
const aws = require('aws-sdk')
const config = require('../config.json')
const fetch = require('node-fetch')
const expireStamp = 604800 // 7 days
const existsModule = require('./existsModule')
module.exports = async function(toSignFile) {
let checkJSON = await existsModule(`${toSignFile}.json`)
if (checkJSON == true) {
let testURL = await s3signing(`${toSignFile}.json`)
fetch(testURL, {
method: 'PUT',
body: JSON.stringify(`This is a write test: ${Date.now()}`),
}).then((res) => {
console.log(res)
}).catch((err) => {
console.log(`Fetch issue: ${err}`)
})
}
}
async function s3signing(signFile) {
const s3 = new aws.S3()
aws.config.update({
accessKeyId: config.aws.accessKey,
secretAccessKey: config.aws.secretKey,
region: config.aws.region,
})
params = {
Bucket: config.aws.bucket,
Key: signFile,
Expires: expireStamp
}
try {
// let signedURL = await s3.getSignedUrl('getObject', params)
let signedURL = await s3.getSignedUrl('putObject', params)
console.log('\x1b[36m%s\x1b[0m', `Signed URL: ${signedURL}`)
return signedURL
} catch (err) {
return err
}
}
查看权限我没有关于上传的问题,并且在权限中设置了写访问权限。在Node中,如何使用该文件的预签名URL作为路径写入S3存储桶中的文件?
答案 0 :(得分:1)
fs
是文件系统模块。您不能将其用作HTTP客户端。
您可以使用内置的https
模块,但我想您会发现使用node-fetch会更容易。
fetch('your signed URL here', {
method: 'PUT',
body: JSON.stringify(data),
// more options and request headers and such here
}).then((res) => {
// do something
}).catch((e) => {
// do something else
});
答案 1 :(得分:0)
正在寻找一种优雅的方法来使用PUT将s3文件传输到s3签名的url。我发现的大多数示例都使用PUT({body:data})。我遇到了一个建议,将数据读取到可读流中,然后将其通过管道传输到PUT。但是,我仍然不喜欢将大文件加载到内存中,然后将其分配给put流的想法。用管道读和写总是在内存和性能上更好。由于s3.getObject()。createReadStream()返回支持管道的请求对象,因此我们要做的就是将其正确地管道传递到公开写入流的PUT请求。
获取对象函数
async function GetFileReadStream(key){
return new Promise(async (resolve,reject)=>{
var params = {
Bucket: bucket,
Key: key
};
var fileSize = await s3.headObject(params)
.promise()
.then(res => res.ContentLength);
resolve( {stream : s3.getObject(params).createReadStream(),fileSize});
});
}
放置对象功能
const request = require('request');
async function putStream(presignedUrl,readStream){
return new Promise((resolve,reject)=>{
var putRequestWriteStream = request.put({url:presignedUrl,headers:{'Content-Type':'application/octet-stream','Content-Length':readStream.fileSize }});
putRequestWriteStream.on('response', function(response) {
var etag = response.headers['etag'];
resolve(etag);
})
.on('end', () =>
console.log("put done"))
readStream.stream.pipe(putRequestWriteStream);
});
}
这非常适合占用很小的内存空间。享受。