为什么express的res.download()方法导致“请求中止”错误?

时间:2018-06-22 20:55:52

标签: javascript node.js http express download

我从使用node.js框架的express服务器获得以下代码:

var fs = require('fs')
    express = require('express')
    handlebars = require('express-handlebars');

var helpers = require('./lib/helpers');

var app = express();

app.use(function(req, res, next){
   var pathUrl = req.path; 
   if(pathUrl !== '/')
   res.download(__dirname + '/' + 'download.png', 'download.png', function(err){
      console.log(err);
   });
   next();
});

app.get('/', function(req, res){
   res.send('<a href=' + '/download.png' + '>' + 'download' + '</a>');
});

app.listen(3001);

运行时,此代码创建以下错误:

{ Error: Request aborted
    at onaborted (/home/js/webdev/fs/node_modules/express/lib/response.js:1021:15)
    at Immediate._onImmediate (/home/js/webdev/fs/node_modules/express/lib/response.js:1063:9)
    at runCallback (timers.js:696:18)
    at tryOnImmediate (timers.js:667:5)
    at processImmediate (timers.js:649:5) code: 'ECONNABORTED' }

如果res.download()更改为res.send('Helo'),则可以使用。

为什么res.download()不起作用?

谢谢。

1 个答案:

答案 0 :(得分:1)

您不允许res.download()完成

Error: Request aborted表示快递没有机会完成其需要发送的内容。

调用res.download()时,等同于执行res.send(),只是要确保它具有足够的标头让浏览器知道它是文件下载,而不是在浏览器中显示。此函数调用为异步,这意味着它将继续在后台运行,然后运行下一行代码,在本例中为next()

next()被调用,然后告诉express继续寻找匹配的路由,或者在这种情况下,不再有匹配的路由和express将终止连接。这不是您想要的,因为您仍在尝试完成文件下载。完成时,您不需要特快告诉您,您完成时,您只需说出

如何解决?

非常简单,如果路由不是/,请确保express 不能继续到中间件中的下一条路由。在您的条件中添加else子句:

app.use(function(req, res, next){
   var pathUrl = req.path;
   if(pathUrl !== '/') {
       res.download(__dirname + '/' + 'download.png', 'download.png', function(err){
          console.log(err);
       });
   } else {
       next();
   }
});

脚注

这不是在这里完成您要完成的操作的最简单方法。您可以使用通配符路由匹配(*)来简化此过程。我已经对您的代码进行了一些整理,其中包括一些功能。

const path = require("path");
const express = require("express");
const app = express();

app.get("/", (req, res) => res.send(`<a href="/download.png">download</a>`));

app.get("*", (req, res) => {
    res.download(path.join(__dirname, "./download.png"), "download.png", err => {
        if (err) console.log(err);
    });
});

app.listen(3001);
  • (req, res) => {}是写作function(req, res) {}的{​​{3}}
  • path模块cleaner way,因为它可以处理多个操作系统
  • *通配符路由将匹配任何内容,并且通常应始终排在最后
  • 我们现在在err之前检查是否有console.log()