有没有办法使用 node.js 从 url 上传到 S3?

Posted

技术标签:

【中文标题】有没有办法使用 node.js 从 url 上传到 S3?【英文标题】:Is there a way to upload to S3 from a url using node.js? 【发布时间】:2013-05-24 02:06:42 【问题描述】:

我找到了这个问题,但它似乎没有回答我的问题,因为我认为它仍在谈论本地文件。

我想获取 imgur.com 链接并使用节点将其上传到 S3。 knox 能做到这一点还是我需要使用其他东西?

不知道从哪里开始。

【问题讨论】:

许多答案表明“接受”的答案可能不是正确的,这可能需要更新和支持其他相关答案。当然,没有义务这样做。 【参考方案1】:

我用的不是knox,而是官方的AWS SDK for javascript in Node.js。我向带有encoding: null 的URL 发出请求,以检索缓冲区中的数据,这些数据可以直接传递给s3.putObject()Body 参数。下面是使用aws-sdk 和request 将远程图像放入存储桶的示例。

var AWS = require('aws-sdk');
var request = require('request');

AWS.config.loadFromPath('./config.json');
var s3 = new AWS.S3();

function put_from_url(url, bucket, key, callback) 
    request(
        url: url,
        encoding: null
    , function(err, res, body) 
        if (err)
            return callback(err, res);

        s3.putObject(
            Bucket: bucket,
            Key: key,
            ContentType: res.headers['content-type'],
            ContentLength: res.headers['content-length'],
            Body: body // buffer
        , callback);
    )


put_from_url('http://a0.awsstatic.com/main/images/logos/aws_logo.png', 'your_bucket', 'media/aws_logo.png', function(err, res) 
    if (err)
        throw err;

    console.log('Uploaded data successfully!');
);

【讨论】:

我采用的方法完全相同。我的图像文件在 S3 上损坏了 :( +1 为例。我的方法也与此类似,但我遇到了损坏的上传问题。不过,这段代码似乎对我有用。 如果你使用 axios - 设置 header responseType: 'stream' 这对我有用。为了避免损坏的图像问题,我必须确保在请求选项中设置了 encoding: null @Alexander,您的评论对我帮助很大!谢谢!【参考方案2】:

对于那些正在寻找doesn't involves callbacks 的解决方案并且更喜欢promises 的人,这里是基于@micmia 代码的替代方案:

var AWS = require('aws-sdk'),
request = require('request');


const bucketName='yourBucketName';
const bucketOptions = ...Your options;
var s3 = new AWS.S3(options);

function UploadFromUrlToS3(url,destPath)
    return new Promise((resolve,reject)=>             
        request(
            url: url,
            encoding: null
        , function(err, res, body)         
            if (err)
                reject(err);
            
            var objectParams = 
                ContentType: res.headers['content-type'],
                ContentLength: res.headers['content-length'],
                Key: destPath,
                Body: body 
            ;
            resolve(s3.putObject(objectParams).promise());
        );
    );


UploadFromUrlToS3(
    'http://a0.awsstatic.com/main/images/logos/aws_logo.png',
    'your/s3/path/aws_logo.png' )
    .then(function() 
        console.log('image was saved...');
    ).catch(function(err) 
        console.log('image was not saved!',err);
    );

【讨论】:

【参考方案3】:

在@Yuri 的帖子的基础上,对于那些想要使用axios 而不是request 和ES6 语法来获得更现代方法的人+ 将所需的Bucket 属性添加到params(它会下载任何文件,不仅是图片):

const uploadFileToS3 = (url, bucket, key) => 
  return axios.get(url,  responseType: "arraybuffer", responseEncoding: "binary" ).then((response) => 
    const params = 
      ContentType: response.headers["content-type"],
      ContentLength: response.data.length.toString(), // or response.header["content-length"] if available for the type of file downloaded
      Bucket: bucket,
      Body: response.data,
      Key: key,
    ;
    return s3.putObject(params).promise();
  );


uploadFileToS3(<your_file_url>, <your_s3_path>, <your_s3_bucket>)
   .then(() => console.log("File saved!"))
   .catch(error) => console.log(error));

【讨论】:

【参考方案4】:

与上述答案相同,但使用 fetch:

async function upload(url: string, key: string, bucket: string) 
  const response = await fetch(url)
  const contentType = response.headers.get("content-type") ?? undefined;
  const contentLength =
    response.headers.get("content-length") != null
      ? Number(response.headers.get("content-length"))
      : undefined;

  return s3
    .putObject(
      Bucket: bucket,
      Key: key,
      ContentType: contentType,
      ContentLength: contentLength,
      Body: response.body, // buffer
    )
    .promise();

【讨论】:

【参考方案5】:

是的。在 knox README 中有一个这样做的例子

http.get('http://google.com/doodle.png', function(res)
  var headers = 
      'Content-Length': res.headers['content-length']
    , 'Content-Type': res.headers['content-type']
  ;
  client.putStream(res, '/doodle.png', headers, function(err, res)
    // Logic
  );
);

【讨论】:

没有理由讽刺和粗鲁。

以上是关于有没有办法使用 node.js 从 url 上传到 S3?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Node 中的图像 url 将图像上传到 Google Cloud Storage?

有没有办法从 URL 上传到 Cloud Storage?

有没有办法直接从 cPanel 的文件管理器中的 URL 上传文件

如何在上传后立即接收 Cloudinary 图像 URL(React JS 和 Node Js)?

在 Node.js 中使用 POST 请求上传文件

Angular、Node.js、MySQL 图片上传