Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/33.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js 使用Express以流的形式获取上载的文件_Node.js_Express_Http_File Upload_Upload - Fatal编程技术网

Node.js 使用Express以流的形式获取上载的文件

Node.js 使用Express以流的形式获取上载的文件,node.js,express,http,file-upload,upload,Node.js,Express,Http,File Upload,Upload,现在,我正在尝试制作一个API,它的功能之一是获取一个文件并将其上传到另一个网站,就像通过API作为某种“代理”上传文件一样 我将文件发送到的网站需要额外的工作步骤(即在另一个请求中发送目的地),我希望让我的API在一个请求中完成这一切,而该请求已经包含了所需的所有详细信息 我已经完成了对目的地的请求,但是我很难找到如何将用户的上传“管道化”到我发送到网站的请求中RequestPromise在上传文件时将文件流作为输入,因此我希望通过管道将来自用户的上传传输到请求。这样,我就不必使用任何磁盘空间

现在,我正在尝试制作一个API,它的功能之一是获取一个文件并将其上传到另一个网站,就像通过API作为某种“代理”上传文件一样

我将文件发送到的网站需要额外的工作步骤(即在另一个请求中发送目的地),我希望让我的API在一个请求中完成这一切,而该请求已经包含了所需的所有详细信息

我已经完成了对目的地的请求,但是我很难找到如何将用户的上传“管道化”到我发送到网站的请求中
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};

我建议您做以下几点:

  • 更改您的端点,以便在URL中发送
    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解析器。您需要检查哪些扩展名?我只需要确定请求是否包含文件(这样我就可以相应地提供响应,说明请求中缺少该文件)。据我所知,我不认为我必须检查扩展名。