从 url 下载文件并将其上传到 AWS S3 而不保存 - node.js
Posted
技术标签:
【中文标题】从 url 下载文件并将其上传到 AWS S3 而不保存 - node.js【英文标题】:Download file from url and upload it to AWS S3 without saving - node.js 【发布时间】:2014-04-06 21:00:01 【问题描述】:我正在编写一个应用程序,它从 url 下载图像,然后使用 aws-sdk 将其上传到 S3 存储桶。
以前我只是像这样下载图像并将它们保存到磁盘。
request.head(url, function(err, res, body)
request(url).pipe(fs.createWriteStream(image_path));
);
然后像这样将图像上传到 AWS S3
fs.readFile(image_path, function(err, data)
s3.client.putObject(
Bucket: 'myBucket',
Key: image_path,
Body: data
ACL:'public-read'
, function(err, resp)
if(err)
console.log("error in s3 put object cb");
else
console.log(resp);
console.log("successfully added image to s3");
);
);
但我想跳过将图像保存到磁盘的部分。有什么方法可以pipe
将来自request(url)
的响应发送到变量然后上传?
【问题讨论】:
这可以在 ios 中做同样的事情吗? 【参考方案1】:这里有一些 javascript 可以很好地做到这一点:
var options =
uri: uri,
encoding: null
;
request(options, function(error, response, body)
if (error || response.statusCode !== 200)
console.log("failed to get image");
console.log(error);
else
s3.putObject(
Body: body,
Key: path,
Bucket: 'bucket_name'
, function(error, data)
if (error)
console.log("error downloading image to s3");
else
console.log("success uploading to s3");
);
);
【讨论】:
如所写,代码一次将整个主体加载到内存中(作为字符串加载到“body”变量中)。也就是说,这不会直接从请求流向 S3。 OTOH,如果“encoding”为空,request 将为“body”创建一个 Buffer 对象;见github.com/request/request#requestoptions-callback。我建议对此答案进行编辑,将encoding:'binary'
更改为encoding:null
并消除body=new Buffer(body,'binary')
。这将消除将整个“正文”存储在内存中的需要,我认为这与原始问题和答案一致。但评论想要评论......
我尝试了你的方法,无论是隐式编码还是显式编码,我发现我上传的 png 文件由于某种原因已损坏,无法弄清楚原因。试图复制这张图片openclipart.org/image/250px/svg_to_png/264091/MirrorCarp.png,这就是我在我的桶里得到的images.quickhunts.com/clipart/23234234234.png
@Ilanlewin 它绝对适用于png
图像,但请确保您正确实施fs.readFile
。自从我最初写这个答案以来,它可能已经改变了,你可能需要更具体的编码。也可以尝试一些jpg
s 或其他通用图像。
我试图将 PDF 从远程 URL 存储到 S3。但上传后PDF已损坏。 @ArmadilloJim 对encoding: null
的修复似乎对我有用。
我想将此解决方案应用于我的应用,但请求模块已弃用我想使用 axios 迁移代码有人可以帮助我吗?【参考方案2】:
这就是我所做的并且效果很好:
const request = require('request-promise')
const AWS = require('aws-sdk')
const s3 = new AWS.S3()
const options =
uri: uri,
encoding: null
;
async load()
const body = await request(options)
const uploadResult = await s3.upload(
Bucket: 'bucket_name',
Key : path,
Body : body,
).promise()
【讨论】:
能否指定路径参数【参考方案3】:这样的事情呢:
const stream = require('stream');
const request = require('request');
const s3 = new AWS.S3()
const pass = new stream.PassThrough();
request(url).pipe(pass);
s3.upload(
Bucket: 'bucket_name',
Key: path,
Body: pass,
);
【讨论】:
【参考方案4】:你可以像这样用 Axios 实现。更多信息请参考this。
const axios = require("axios");
const AWS = require("aws-sdk");
const PassThrough = require("stream");
const s3 = new AWS.S3(
accessKeyId: "accessKeyId",
secretAccessKey: "accessKey",
region: "region",
);
const bucket = "BucketName";
const key = "key";
const uploadToS3 = async (bucket, key) =>
try
const stream = await axios.get(url, responseType: "stream" );
const passThrough = new PassThrough();
const response = s3.upload( Bucket: bucket, Key: key, Body: passThrough );
stream.data.pipe(passThrough);
return response.then((data) => data.Location).catch((e) => console.error(e));
catch (error)
console.error(error);
;
uploadToS3(bucket, key);
【讨论】:
【参考方案5】:import axios from "axios";
import aws from 'aws-sdk'
import crypto from 'crypto'
const s3 = new aws.S3();
export const urlToS3 = async ( url, bucket = "rememoio-users", key = Date.now() + crypto.randomBytes(8).toString('hex') + ".png" ) =>
try
const data = await axios.get(url, responseType: "stream" );
const upload = await s3.upload(
Bucket: bucket,
ACL: 'public-read',
Key: key,
Body: data,
).promise();
return upload.Location;
catch (error)
console.error(error);
throw new Error;
;
【讨论】:
以上是关于从 url 下载文件并将其上传到 AWS S3 而不保存 - node.js的主要内容,如果未能解决你的问题,请参考以下文章
Android-Amplify:使用 Amplify 向/从 AWS S3 上传/下载文件