文本/纯文件下载的 Angular http$ 响应失败,并出现 SyntaxError:JSON 中的意外数字

Posted

技术标签:

【中文标题】文本/纯文件下载的 Angular http$ 响应失败,并出现 SyntaxError:JSON 中的意外数字【英文标题】:Angular http$ response for text/plain file download fails with SyntaxError: Unexpected number in JSON 【发布时间】:2016-10-12 01:04:43 【问题描述】:

我基于以下解决方案在基于 Angular 的客户端和 node.js 后端实现了下载文件功能:https://***.com/a/20904398/1503142。一般来说,这是可行的,但有时我会收到“SyntaxError:JSON 中位置 x 的意外数字”以及“TypeError:无法读取未定义的属性‘消息’”。

一些观察:

节点服务器端似乎一切正常,因为我总是在客户端得到响应。有问题的错误由客户端报告;服务器未报告任何错误。 日志文件由时间戳和基本日志信息文本组成。文本可以包含 ASCII 字符 使用 Postman,响应每次都有效,这使人们认为可能是响应有问题的是 http$ 代码。 Postman的响应Header信息表明响应是Content-Type->text/plain; charset=utf-8。 我正在使用 AngularJS v1.2.21 和 Node v0.12.13

这是客户端代码:

$http(
    method: 'GET',
    url: "/api/logging/logfiles/" + logFile,
    headers:  'Content-Type': 'text/plain;charset=utf-8' 
).
success(function (data, status, headers, config) 
    var anchor = angular.element('<a/>');
    anchor.attr(
        href: 'data:text/plain;charset=utf-8,' + encodeURIComponent(data),
        target: '_blank',
        download: logFile
    )[0].click();
).
error(function (data, status, headers, config) 
    console.log('Hence my visit to ***!')
);

这是服务器端代码:

app.get('/api/logging/logfiles/:logfile', function (req, res, next) 
  logDirectory = './log';
  fs.readFile(logDirectory + "/" + req.params.logfile, 'utf8', function (err, data) 
    if (err) 
        res.send("Something broke!");
    
    else 
        res.set( 'Content-Type': 'text/plain; charset=utf-8' );
        res.send(data);
    
  );
);

我怀疑这与日志文件的内容有关。既然我指定了 text/plain 内容,为什么会出现 JSON 解析错误?

【问题讨论】:

需要在请求中设置dataType而不是header。请求标头没有意义,因为 GET 请求没有内容类型 你能检查一下 mimetype 吗? mime.lookup(logDirectory + "/" + req.params.logfile) 【参考方案1】:

试试这个:

app.get('/api/logging/logfiles/:logfile', function (req, res, next) 
  logDirectory = './log';
  res.sendFile(logDirectory + "/" + req.params.logfile);

);

【讨论】:

使用您的建议,我得到了完全相同的错误。我认为这进一步证明了这是一个客户端问题。虽然我承认这是更严格的代码。【参考方案2】:

显而易见的答案是在发送之前对文件进行编码以确保安全通过,然后在浏览器中解码回文件内容。似乎某些特殊字符影响了客户端对传入数据的处理(可能是双引号):

所以在客户端,我现在正在这样做:

$http(
  method: 'GET',
  url: "/api/logging/logfiles/" + logFile
  // Removed unncessary dataType based on charlietfl's comment
).
success(function (data, status, headers, config) 
  var anchor = angular.element('<a/>');
  anchor.attr(
    // decode the file to go back to raw data
    href: 'data:text/plain;charset=utf-8,' + decodeURI(data),
    target: '_blank',
    download: logFile
  )[0].click();
).
error(function (data, status, headers, config) 
  console.log('Hence my visit to ***!')
);

服务器端是:

app.get('/api/logging/logfiles/:logfile', function (req, res, next) 
  logDirectory = './log';
  fs.readFile(logDirectory + "/" + req.params.logfile, 'utf8', function (err, data) 
    if (err) 
       res.send("Something broke!");
    
    else 
      res.set( 'Content-Type': 'text/plain; charset=utf-8' );
      // Encode the data to remove characters that might
      // present issues to the client
      res.send(encodeURI(data));
    
  );
);

【讨论】:

以上是关于文本/纯文件下载的 Angular http$ 响应失败,并出现 SyntaxError:JSON 中的意外数字的主要内容,如果未能解决你的问题,请参考以下文章

纯/文本的 Angular 8/httpclient 错误响应,无法解析响应

Angular2将纯文本转换为url的方式(锚链接)

爬虫从入门到放弃 - 纯新手学习-爬虫基本原理

web框架学习

Django基础之前戏

Angular:HTTP GET 请求 - OPTIONS 405(不允许的方法)