javascript - 使用 Axios 进行 Amazon S3 远程文件上传
问题描述
我正在尝试编写一个函数:
- 以远程 URL 作为参数,
- 使用 axios 获取文件
- 将流上传到亚马逊 s3
- 最后,返回上传的 url
我在 stackoverflow 上找到了帮助。到目前为止,我有这个:
/*
* Method to pipe the stream
*/
const uploadFromStream = (file_name, content_type) => {
const pass = new stream.PassThrough();
const obj_key = generateObjKey(file_name);
const params = { Bucket: config.bucket, ACL: config.acl, Key: obj_key, ContentType: content_type, Body: pass };
s3.upload(params, function(err, data) {
if(!err){
return data.Location;
} else {
console.log(err, data);
}
});
return pass;
}
/*
* Method to upload remote file to s3
*/
const uploadRemoteFileToS3 = async (remoteAddr) => {
axios({
method: 'get',
url: remoteAddr,
responseType: 'stream'
}).then( (response) => {
if(response.status===200){
const file_name = remoteAddr.substring(remoteAddr.lastIndexOf('/')+1);
const content_type = response.headers['content-type'];
response.data.pipe(uploadFromStream(file_name, content_type));
}
});
}
但uploadRemoteFileToS3
不返回任何东西(因为它是一个异步函数)。如何获取上传的网址?
更新
我进一步改进了代码并编写了一个类。这是我现在拥有的:
const config = require('../config.json');
const stream = require('stream');
const axios = require('axios');
const AWS = require('aws-sdk');
class S3RemoteUploader {
constructor(remoteAddr){
this.remoteAddr = remoteAddr;
this.stream = stream;
this.axios = axios;
this.config = config;
this.AWS = AWS;
this.AWS.config.update({
accessKeyId: this.config.api_key,
secretAccessKey: this.config.api_secret
});
this.spacesEndpoint = new this.AWS.Endpoint(this.config.endpoint);
this.s3 = new this.AWS.S3({endpoint: this.spacesEndpoint});
this.file_name = this.remoteAddr.substring(this.remoteAddr.lastIndexOf('/')+1);
this.obj_key = this.config.subfolder+'/'+this.file_name;
this.content_type = 'application/octet-stream';
this.uploadStream();
}
uploadStream(){
const pass = new this.stream.PassThrough();
this.promise = this.s3.upload({
Bucket: this.config.bucket,
Key: this.obj_key,
ACL: this.config.acl,
Body: pass,
ContentType: this.content_type
}).promise();
return pass;
}
initiateAxiosCall() {
axios({
method: 'get',
url: this.remoteAddr,
responseType: 'stream'
}).then( (response) => {
if(response.status===200){
this.content_type = response.headers['content-type'];
response.data.pipe(this.uploadStream());
}
});
}
dispatch() {
this.initiateAxiosCall();
}
async finish(){
//console.log(this.promise); /* return Promise { Pending } */
return this.promise.then( (r) => {
console.log(r.Location);
return r.Location;
}).catch( (e)=>{
console.log(e);
});
}
run() {
this.dispatch();
this.finish();
}
}
但是仍然不知道如何在承诺解决时捕获结果。到目前为止,我尝试了这些:
testUpload = new S3RemoteUploader('https://avatars2.githubusercontent.com/u/41177');
testUpload.run();
//console.log(testUpload.promise); /* Returns Promise { Pending } */
testUpload.promise.then(r => console.log); // does nothing
但以上都不起作用。我有一种感觉,我错过了一些非常微妙的东西。任何线索,任何人?
解决方案
上传后,您可以调用 s3 sdk 中的 getsignedurl 函数来获取 url,您还可以在其中指定 url 的到期时间。您需要传递该功能的密钥。现在旅行将在稍后更新示例。
要生成一个简单的预签名 URL,允许任何用户查看您拥有的存储桶中的私有对象的内容,您可以使用以下 getSignedUrl() 调用:
var s3 = new AWS.S3();
var params = {Bucket: 'myBucket', Key: 'myKey'};
s3.getSignedUrl('getObject', params, function (err, url) {
console.log("The URL is", url);
});
官方文档链接 http://docs.amazonaws.cn/en_us/AWSJavaScriptSDK/guide/node-examples.html
代码必须是这样的
function uploadFileToS3AndGenerateUrl(cb) {
const pass = new stream.PassThrough();//I have generated streams from file. Using this since this is what you have used. Must be a valid one.
var params = {
Bucket: "your-bucket", // required
Key: key , // required
Body: pass,
ContentType: 'your content type',
};
s3.upload(params, function(s3Err, data) {
if (s3Err) {
cb(s3Err)
}
console.log(`File uploaded successfully at ${data.Location}`)
const params = {
Bucket: 'your-bucket',
Key: data.key,
Expires: 180
};
s3.getSignedUrl('getObject', params, (urlErr, urlData) => {
if (urlErr) {
console.log('There was an error getting your files: ' + urlErr);
cb(urlErr);
} else {
console.log(`url: ${urlData}`);
cb(null, urlData);
}
})
})
}
推荐阅读
- html - 如何删除我的部分标签顶部的空间
- vue.js - 在 CPanel 上部署 Nuxtjs
- kubernetes - kubernetes/ingress-nginx 创建大量同步事件
- javascript - “在新标签中打开”单击链接未打开 href 值
- dask - 从远程 ssh 服务器读取图像到 dask 数组
- c++ - 如何在 ubuntu linux 上重新安装 gcc 和 g++
- redis - 从客户的角度来看 AWS Elasticache 故障转移
- c# - Httpclient优化提升性能
- android - 在 autocompletetextview 的下拉列表中设置多个布局
- git - 在 git alias 中使用 awk:别名通过完整的本地参考名称删除远程分支 `git push -d remotes/remote-name/topic/branch`