如何处理来自Express response.write()的响应在Angular $http中

3

我正在尝试使用ng-file-upoad上传一个csv文件。这是我的代码片段:

Upload.upload({
   url: baseUrl + '/file-upload',
   data: {
      file: file
   }
 })
 .then(function(res) {
    console.log('success: ===> ', res);
 }, function(err) {
    console.log('erroir: ===> ', err);
 }, function() {
    console.log('progress: ', arguments);
 });

在Node环境中,我正在解析文件并将数据插入到数据库中。我不想关闭连接。这就是为什么我使用了“response.write”。以下是我的代码片段:

var path = req.files.file.path,
    currentIndex = 0;

fs.readFile(path, 'utf8', function(err, data) { 
    if(err) {
         // handle error
    } else {
        // making array (dataArray) from data
        dataArray.forEach(function(eachData){
            newEntry = new app.db.models.SomeCollection(eachData);
            newEntry.save(function(err, data) {
              if (currentIndex === dataArray.length) {
                 res.end('DONE!');
              } else {
                  currentIndex++;
                  res.write(JSON.stringify({
                     total: dataArray.length,
                     done: currentIndex
                  }));
              }
            });
        })
    }
});

我的问题是如何获取我在“res.write”中传递的数据?我不想仅为此目的使用套接字。我是否漏掉了什么?

“我不想关闭连接”是什么意思? - Alexandr Lazarev
我不想使用response.send或response.end。实际上,该文件包含5000个数据,我想根据服务器的响应显示进度条。除了socket之外,是否有其他发送数据的方法? - Kaushick Gope
1
通过ajax请求建立的连接将在您发送响应后关闭。否则,您必须使用套接字连接。 “我不想仅出于这个目的使用套接字” - 套接字连接还有什么其他用途吗..?您唯一最接近的选择是实现长轮询。 - T J
你不能只用一个 http 请求来完成它。你应该创建一个套接字并将流传输到那里,或者你应该从客户端向服务器发出多个 http 请求。 - Alexandr Lazarev
我知道这是一个老问题,但我现在也面临着同样的问题。自那以后你找到答案了吗? - Nelson Teixeira
2个回答

1

如已在此处解释:

response.send(msg)等同于response.write(msg);response.end();

这意味着,send只能调用一次,write可以被多次调用,但你必须自己调用end。

你可能无法接收响应,因为缺少response.end()

一旦你end()了响应,你就应该能够在Upload.upload promise中访问响应数据。

这不像你所说的“关闭连接”。这不是一种类似于套接字(如ws或socket.io)的实现。一旦请求被发出,即使是提供有关该请求的错误详细信息(例如状态401、403、404等),它也应该有一个响应。


我已经检查了那个链接。但是我不想使用response.send或response.end。实际上,该文件包含5000条数据,我想根据服务器的响应显示进度条。有没有办法从服务器发送数据? - Kaushick Gope
看一下这篇博客:http://www.jonahnisenson.com/file-uploads-using-angular-and-nodeexpress/。它解释了如何在Angular中实现文件上传期间的进度。它是在客户端而不是服务器端实现的。 - pgrodrigues
1
我不是在谈论文件上传进度,请仔细阅读问题。我正在处理文件上传完成后的数据。我想显示插入数据的进度,而不是文件上传百分比。 - Kaushick Gope

0

在你的 Angular 组件中:

  ...
  constructor(private incrementalService: IncrementalService) {}
   
  incrementalTest() { //activate with a button or whatnot
    this.incrementalService.increment().subscribe( (result:any) => {
      if (result.partialText) {
        console.log(partialText); //do whatever you need to do with your partial results here!
      }
    })
  }

你的 Angular 服务:

   import { HttpClient, HttpHeaders } from '@angular/common/http';
   public class IncrementalService {

     constructor(private http: HttpClient) {}

     increment(): Observable<ArrayBuffer> {
        const options = {
          reportProgress: true,
          responseType: 'text',
          observe: 'events'
        }
        return this.http.request('get', 'http://someURL', { ...this.addRawHeaderOptions(), ...options});
     }

     private addRawHeaderOptions() {
        const authHeaders = new HttpHeaders({
          'Content-Type': 'application/json',
          //authorization, Cache-Control: 'no-cache, Pragma:'no-cache', et al.     }
        return { headers: authHeaders }
     }
   }

最后,你的后端服务(这里是express,但对原始的node应该也类似):

  async function(request, response) {
    const increments = [ 1,2,3,4 ];
    response.set('Content-Type', 'text/html');
    for (const value of increments) { //contains async call - not switch-outable for a forEach.
      response.write(`increment - ${value} `);
      const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
      await delay(1000)
    }
    response.status(200).end()
  }

运行时的浏览器控制台输出:

  • 增量 - 1
  • 增量 - 1 增量 - 2
  • 增量 - 1 增量 - 2 增量 - 3
  • 增量 - 1 增量 - 2 增量 - 3 增量 - 4

!!抱歉可能有错别字 - 我不得不从一个被锁定的机器上转录这个。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接