简体   繁体   English

使用 Axios 进行 Amazon S3 远程文件上传

[英]Amazon S3 Remote File Upload with Axios

I am trying to write a function that would:我正在尝试编写一个函数:

  1. Take a remote URL as a parameter,以远程 URL 作为参数,
  2. Get the file using axios使用 axios 获取文件
  3. Upload the stream to amazon s3将流上传到亚马逊 s3
  4. And finally, return the uploaded url最后,返回上传的 url

I found help here on stackoverflow .在 stackoverflow 上找到了帮助。 So far, I have this:到目前为止,我有这个:

/* 
 * 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));
        }
    });
}

But uploadRemoteFileToS3 does not return anything (because it's a asynchronous function).但是uploadRemoteFileToS3不返回任何东西(因为它是一个异步函数)。 How can I get the uploaded url?如何获取上传的网址?

UPDATE更新

I have further improved upon the code and wrote a class.我进一步改进了代码并编写了一个类。 Here is what I have now:这是我现在所拥有的:

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();
    }
}

But still have no clue how to catch the result when the promise is resolved.但是仍然不知道如何在解决承诺时捕获结果。 So far, I tried these:到目前为止,我尝试了这些:

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

But none of the above works.但以上都不起作用。 I have a feeling I am missing something very subtle.我有一种感觉,我错过了一些非常微妙的东西。 Any clue, anyone?任何线索,任何人?

After an upload you can call the getsignedurl function in s3 sdk to get the url where you can also specify the expiry of the url as well.上传后,您可以调用 s3 sdk 中的 getsignedurl 函数来获取 url,您还可以在其中指定 url 的到期时间。 You need to pass the key for that function.您需要传递该函数的密钥。 Now travelling will update with example later.现在旅行将在稍后更新示例。

To generate a simple pre-signed URL that allows any user to view the contents of a private object in a bucket you own, you can use the following call to getSignedUrl():要生成一个简单的预签名 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); 
 });

Official documentation link http://docs.amazonaws.cn/en_us/AWSJavaScriptSDK/guide/node-examples.html官方文档链接http://docs.amazonaws.cn/en_us/AWSJavaScriptSDK/guide/node-examples.html

Code must be something like this代码必须是这样的

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);

        }
    })
})
}

Please check i have update your code might its help you.请检查我是否更新了您的代码可能对您有所帮助。

    /*
         * Method to upload remote file to s3
         */
        const uploadRemoteFileToS3 = async (remoteAddr) => {
            const response = await axios({
                method: 'get',
                url: remoteAddr,
                responseType: 'stream'
            })
               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));
                }
                return new Promise((resolve, reject) => {
                    response.data.on('end', (response) => {
                      console.log(response)
                      resolve(response)
                    })

                    response.data.on('error', () => {
                      console.log(response);
                      reject(response)
                    })
              })
        };

       * 
     * Method to pipe the stream 
     */
    const uploadFromStream = (file_name, content_type) => {
       return new Promise((resolve, reject) => {
          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){
                console.log(data)
                return resolve(data.Location);
            } else {
                console.log(err)
                return reject(err);
            }
          });
       });
    }

//call uploadRemoteFileToS3
    uploadRemoteFileToS3(remoteAddr)
      .then((finalResponse) => {
            console.log(finalResponse)
       })
       .catch((err) => {
         console.log(err);
    });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM