Node.js 使用Express以流的形式获取上载的文件
现在,我正在尝试制作一个API,它的功能之一是获取一个文件并将其上传到另一个网站,就像通过API作为某种“代理”上传文件一样 我将文件发送到的网站需要额外的工作步骤(即在另一个请求中发送目的地),我希望让我的API在一个请求中完成这一切,而该请求已经包含了所需的所有详细信息 我已经完成了对目的地的请求,但是我很难找到如何将用户的上传“管道化”到我发送到网站的请求中Node.js 使用Express以流的形式获取上载的文件,node.js,express,http,file-upload,upload,Node.js,Express,Http,File Upload,Upload,现在,我正在尝试制作一个API,它的功能之一是获取一个文件并将其上传到另一个网站,就像通过API作为某种“代理”上传文件一样 我将文件发送到的网站需要额外的工作步骤(即在另一个请求中发送目的地),我希望让我的API在一个请求中完成这一切,而该请求已经包含了所需的所有详细信息 我已经完成了对目的地的请求,但是我很难找到如何将用户的上传“管道化”到我发送到网站的请求中RequestPromise在上传文件时将文件流作为输入,因此我希望通过管道将来自用户的上传传输到请求。这样,我就不必使用任何磁盘空间
RequestPromise
在上传文件时将文件流作为输入,因此我希望通过管道将来自用户的上传传输到请求。这样,我就不必使用任何磁盘空间来临时保存文件,特别是因为我的磁盘空间非常有限,而且我要将文件发送到的服务器实际上没有文件限制
到目前为止,我正在使用express fileupload
临时保存文件,但这最终会占用我非常小(194MB)的分配空间。我正在使用express
v4.16.4和节点v12.0.0。对于请求,我使用requestpromise
v4.2.4
下面是我如何声明Express应用程序和Express fileupload
对象的
var-router=express.router({区分大小写:true});
应用程序使用(路由器);
...
路由器。使用(需要(“快速文件上传”)({
useTempFiles:true,
tempFileDir:“.data/temp”
}));
下面是我用来将文件放入网站的方法:
if(req.body.id==未定义| | req.files.file==未定义)
返回新的APIError(400);
if(!Object.keys(JSON.parse(fs.read(“.data/master\u list\u of\u可能的值\u for\u该变量.JSON”)))。包括(req.body.id))
返回新的APIRROR(“400-ID”);
var session_flag=wait(session.executeRequest({
方法:“张贴”,
uri:Constants.URL.upload.session,
表格:{
id:req.body.id
}
})
.then(r=>{return r;})
.catch(e=>{returne;}));
if(会话标志instanceof Error)
投掷课时标志;
var upload=await(session.executeRequest({
方法:“张贴”,
uri:Constants.URL.upload.fileEndpoint,
表格数据:{
文件:{
值:fs.createReadStream(req.files.file.tempFilePath),
选项:{
文件名:req.files.file.name,
contentType:req.files.file.mimetype
}
}
}
})
.then(r=>{return r;})
.catch(e=>{returne;}));
如果(上传实例错误)
抛出上传;
返回{success:true};
我建议您做以下几点:
id
,这样您就不需要阅读整个正文来发出第一个请求const request=require('request');//流式处理可以更好地处理请求
const rp=要求(“请求-承诺”);
const{once}=require('events');
//确保没有为此请求启用任何正文解析器
路由器.post('/:id',异步(req,res)=>{
试一试{
//发出第一个请求
等待rp({
方法:“张贴”,
uri:Constants.URL.upload.session,
表格:{
id:req.body.id
}
})
//管道请求
常量上传=请求管道(请求({
方法:“张贴”,
uri:Constants.URL.upload.fileEndpoint,
headers:req.headers//发送相同的内容类型、长度等
}))
//将抛出“错误”
等待一次(上传“响应”)
//如果需要,请检查状态代码
const success=upload.response.statusCode==200;
返回res.json({success})
}捕获(e){
资源状况(500)
.send('错误')
}
});
执行此操作时,您不需要将其存储在临时文件中,因为您正在将其直接传输到第三方端点。您可以显示您已经拥有的吗?因为您需要做的就是:
req.pipe(request)
,特别是您提到的附加步骤。好的,我添加了用于捕获请求、发送初始请求,然后发送实际文件的代码。此外,我在Express文档中看不到req.pipe
。这是新事物吗?此外,我必须在将请求传输到网站之前提交第一个请求,并且处理该请求的参数也在正文中。这不意味着我必须先阅读整个正文(包括文件)吗?你控制前端吗?因为我看到你需要发布的唯一一件事是:id
我确实控制我正在制作的应用程序的前端,但不是我要将文件发送到的网站,这(出于我不知道的原因)需要两个独立的请求,即在一个URL上发送id
,然后在另一个URL上发送实际的文件。谢谢!只是一个小小的跟进:有没有办法检查主体是否包含正确的文件?是的,有,但有点复杂,这取决于您可能需要读取整个文件的文件类型。我建议您让第三方服务器检查它,除非您有充分的理由自己检查它。检查请求是否确实包含文件如何?我是否需要检查req.body
是否未定义?我们使用的是streams,您没有完整的文件,req.body
是空的,或者应该是空的,请确保您没有对该请求使用任何body解析器。您需要检查哪些扩展名?我只需要确定请求是否包含文件(这样我就可以相应地提供响应,说明请求中缺少该文件)。据我所知,我不认为我必须检查扩展名。