【问题标题】:HTTP Get file from different site and return with Express for downloadHTTP 从不同站点获取文件并使用 Express 返回以供下载
【发布时间】:2017-08-30 06:05:53
【问题描述】:

我正在尝试在快速 HTTP 获取请求后从我的 Node 应用程序从另一个站点下载文件,然后返回文件以供下载。我尝试了多种获取文件的方法,使用管道、blob 等,但我在黑暗中掌握。该代码可能会让您更深入地了解我想要实现的目标:

var router = require('express').Router();
var fs = require('fs');
var http = require('http');

router.get('/download/:file', function (req, res, next) {
  http.get('http://anothersite/' + req.params.file, function(response) {
    res.setHeader('Content-disposition', 'attachment; filename=' + req.params.file);
    res.setHeader('Content-type', 'application/octet-stream');
    res.download(fs.createWriteStream(req.params.file).pipe(response));
  });
});

这给了我一个错误“无法管道。不可读”。该文件本身不是常规文件格式(它是来自我们定制软件的文件,具有自己的扩展名)。

我错过了什么?

【问题讨论】:

    标签: node.js express fs


    【解决方案1】:

    你需要在这里使用可读流,而不是可写

    Express res 对象派生自节点的http.ServerResponse,它本身实现了节点的WritableStream 接口。请参阅文档 herehere

    既然如此,我认为您可以直接使用response 参数传递给您的回调,因为那已经是ReadableStream(参见here)。尝试使用这样的可读流:

    router.get('/download/:file', function (req, res, next) {
      http.get('http://anothersite/' + req.params.file, function(response) {
        res.setHeader('Content-disposition', 'attachment; filename=' + req.params.file);
        res.setHeader('Content-type', 'application/octet-stream');
        response.pipe(res);  //  <-- change here
      });
    });
    

    此代码正在运行,节点 v5.0.0 和最新的 chrome:

    const express = require('express');
    const app = express();
    const http = require('http');
    
    app.get('/', (req, res) => {
      http.get('http://www.fillmurray.com/200/300', (response) => {
        res.setHeader('Content-disposition', 'attachment; filename=' + 'hello.jpg');
        res.setHeader('Content-type', 'application/octet-stream');
        response.pipe(res)
      });
    });
    
    app.listen(3001, () => console.log(('listening :)')))
    

    【讨论】:

    • 嗨 aarosil,似乎这会将 [object Object] 放入下载的文件中,而不是实际成为文件。有什么想法吗?
    • 嗨!如果您还有更多问题,您可以在输出[object Object] 的位置复制/粘贴代码吗?谢谢!!!
    • 它在下载的文件中 -> 如果我在记事本中打开文件,它只会显示 [object Object]。我正在使用你的代码。
    • 很抱歉听到这个消息,也许它必须使用编码。我自己试过了,它奏效了,我用代码更新了我的答案,以防万一。
    【解决方案2】:

    您可以将请求库用作: request('http://anothersite/').pipe(fs.createWriteStream('filename.extension'))

    更新:

    如果您愿意通过 http 执行此操作,您可以创建一个写入流,如下所示。成功保存文件后,我认为您可以正确执行res.download()

    var http = require('http')
    
    http.get('http://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png').on('response', function (response) {
        var writeStream = fs.createWriteStream('output.png');
    
        response.pipe(writeStream);
    
        response.on('end', function () {
            console.log('stream completed!')
        });
    
        // This is here incase any errors occur
        writeStream.on('error', function (err) {
            console.log(err);
        });
    
    });
    

    【讨论】:

    • 您好 Tolsee,当我使用请求时如何响应带有文件的 http-get?
    • 你可以简单地通过管道获取如下:request .get('http://google.com/doodle.png') .on('error', function(err) { console.log(err) }) .pipe(res)
    • 我不明白,我遇到了与 Aarosil 解决方案相同的问题。下载的文件不是我从其他服务器获得的原始文件。它只是一个包含 [object Object] 的文本文档
    猜你喜欢
    • 1970-01-01
    • 2019-05-27
    • 1970-01-01
    • 1970-01-01
    • 2011-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多