使用 REST 从 Amazon S3 下载文件 API
Download file from Amazon S3 using REST API
我有自己的 REST API
可以调用,以便 下载 文件。 (最后,文件可以存储在不同类型的服务器中...Amazon s3,本地等...)
要从 s3 获取文件,我应该使用这种方法:
var url = s3.getSignedUrl('getObject', params);
这会给我一个可下载的 link 来调用。
现在,我的问题是,当文件来自 link 时,我如何使用自己的休息 API 下载文件?有没有办法重定向呼叫?
我正在为我的 REST 服务器使用 Hapi
。
{
method: "GET", path: "/downloadFile",
config: {auth: false},
handler: function (request, reply) {
// TODO
reply({})
}
},
Return HTTP 303 重定向,Location
header 设置为 S3 存储桶中 blob 的 public URL。
如果您的存储桶是私有的,那么您需要代理请求而不是执行重定向,除非您的客户也可以访问该存储桶。
不是使用重定向来下载所需的文件,而是 return 从 S3 返回一个 unbufferedStream。 unbufferedStream
可以从 AWS-SDK
中的 HttpResponse
编辑 return。这意味着不需要从 S3 下载文件,然后读入,然后让请求者下载文件。
仅供参考,我在 Express 中使用了这种 getObject()
方法并且从未使用过 Hapi,但是我认为我与路由定义非常接近,但希望它能抓住我正在尝试的本质实现。
Hapi.js路线
const getObject = require('./getObject');
{
method: "GET", path: "/downloadFile",
config: {auth: false},
handler: function (request, reply) {
let key = ''; // get key from request
let bucket = ''; // get bucket from request
return getObject(bucket, key)
.then((response) => {
reply.statusCode(response.statusCode);
response.headers.forEach((header) => {
reply.header(header, response.headers[header]);
});
return reply(response.readStream);
})
.catch((err) => {
// handle err
reply.statusCode(500);
return reply('error');
});
}
},
getObject.js
const AWS = require('aws-sdk');
const S3 = new AWS.S3(<your-S3-config>);
module.exports = function getObject(bucket, key) {
return new Promise((resolve, reject) => {
// Get the file from the bucket
S3.getObject({
Bucket: bucket,
Key: key
})
.on('error', (err) => {
return reject(err);
})
.on('httpHeaders', (statusCode, headers, response) => {
// If the Key was found inside Bucket, prepare a response object
if (statusCode === 200) {
let responseObject = {
statusCode: statusCode,
headers: {
'Content-Disposition': 'attachment; filename=' + key
}
};
if (headers['content-type'])
responseObject.headers['Content-Type'] = headers['content-type'];
if (headers['content-length'])
responseObject.headers['Content-Length'] = headers['content-length'];
responseObject.readStream = response.httpResponse.createUnbufferedStream();
return resolve(responseObject);
}
})
.send();
});
}
我有自己的 REST API
可以调用,以便 下载 文件。 (最后,文件可以存储在不同类型的服务器中...Amazon s3,本地等...)
要从 s3 获取文件,我应该使用这种方法:
var url = s3.getSignedUrl('getObject', params);
这会给我一个可下载的 link 来调用。
现在,我的问题是,当文件来自 link 时,我如何使用自己的休息 API 下载文件?有没有办法重定向呼叫?
我正在为我的 REST 服务器使用 Hapi
。
{
method: "GET", path: "/downloadFile",
config: {auth: false},
handler: function (request, reply) {
// TODO
reply({})
}
},
Return HTTP 303 重定向,Location
header 设置为 S3 存储桶中 blob 的 public URL。
如果您的存储桶是私有的,那么您需要代理请求而不是执行重定向,除非您的客户也可以访问该存储桶。
不是使用重定向来下载所需的文件,而是 return 从 S3 返回一个 unbufferedStream。 unbufferedStream
可以从 AWS-SDK
中的 HttpResponse
编辑 return。这意味着不需要从 S3 下载文件,然后读入,然后让请求者下载文件。
仅供参考,我在 Express 中使用了这种 getObject()
方法并且从未使用过 Hapi,但是我认为我与路由定义非常接近,但希望它能抓住我正在尝试的本质实现。
Hapi.js路线
const getObject = require('./getObject');
{
method: "GET", path: "/downloadFile",
config: {auth: false},
handler: function (request, reply) {
let key = ''; // get key from request
let bucket = ''; // get bucket from request
return getObject(bucket, key)
.then((response) => {
reply.statusCode(response.statusCode);
response.headers.forEach((header) => {
reply.header(header, response.headers[header]);
});
return reply(response.readStream);
})
.catch((err) => {
// handle err
reply.statusCode(500);
return reply('error');
});
}
},
getObject.js
const AWS = require('aws-sdk');
const S3 = new AWS.S3(<your-S3-config>);
module.exports = function getObject(bucket, key) {
return new Promise((resolve, reject) => {
// Get the file from the bucket
S3.getObject({
Bucket: bucket,
Key: key
})
.on('error', (err) => {
return reject(err);
})
.on('httpHeaders', (statusCode, headers, response) => {
// If the Key was found inside Bucket, prepare a response object
if (statusCode === 200) {
let responseObject = {
statusCode: statusCode,
headers: {
'Content-Disposition': 'attachment; filename=' + key
}
};
if (headers['content-type'])
responseObject.headers['Content-Type'] = headers['content-type'];
if (headers['content-length'])
responseObject.headers['Content-Length'] = headers['content-length'];
responseObject.readStream = response.httpResponse.createUnbufferedStream();
return resolve(responseObject);
}
})
.send();
});
}