0

在向终端服务器发送 API 响应后,我想用值链接 NodeJs 中的路由,

为什么:> 上传的文件会有点大(每个 5-50mb)并且需要一些处理,不能让我的 API 用户在我的 NodeJS 代码工作时等待/超时.. 所以需要,1:上传文件并立即发送成功到用户、流程文件(很少有承诺)和通知系统的返回/记录成功/失败。

我的各个代码块已完成并且工作正常(即上传服务和文件处理服务在测试中都很好,并且在单独测试时工作良好。)

现在有了要上传的 API,我添加了以下代码:

router.post('/upload', upload.array('upload_data', multerMaxFiles), (req, res, next) => {
 ////some uploading and processing stuff - works nicely
 res.json({ 'message': 'File uploaded successfully.' });// shown to API client nicely
 console.log("what next? " + utilz.inspect(uploaded_file_paths)) //prints file names on console
 next();
});

问题:

app.use('/api', uploadRoute); //The above code route

//want some processing to be done

app.use(function(req, res, next) {

**want those uploaded file names here**
tried with few response object options but stabs with error
});

使用类似 ....

app.use(someFunction(uploaded_file_names)); **want those uploaded file names as params**

PS:文件上传成功后的任何承诺都会导致“错误:发送后无法设置标题。”,所以在那里写任何东西都没有帮助。

任何建议的人。

——N鲍阿

4

3 回答 3

1

一旦您将响应发送回浏览器(以防止它在长时间处理期间超时),该 http 请求就完成了。您无法在其上发送更多数据,并且尝试这样做会触发服务器端错误。您不能按照您似乎想要的方式“链接路由”,因为一旦您发送了第一个响应,您就无法通过该 http 请求发送更多数据。

有两种常见的方法来处理这个问题。

  1. 作为初始响应的一部分,发回一个事务 ID,然后让客户端每隔几秒钟通过一个 Ajax 调用轮询一次,询问该事务的最终状态是什么。服务器可以返回“进行中”,直到它最终完成,然后它可以返回最终状态。

  2. 您可以连接从客户端到服务器的 webSocket 或 socket.io 连接。作为您对上传的初始响应的一部分,请发回交易 ID。然后,当事务在服务器端完成时,它会在 webSocket 或 socket.io 连接上为该特定客户端发送一个通知,其中包含最终状态的 transactionID。然后客户端可以相应地响应该最终状态。您可以保持 webSocket/socket.io 连接打开以供其他请求使用,也可以关闭该连接。

使用任一技术,您还可以返回/发送客户端可以用来显示完成进度的进度值(如完成百分比)。这在客户端通常非常有用,可以防止不耐烦的用户放弃或刷新页面。如果他们可以看到处理正在进行,他们不会放弃认为它可能停止工作的想法。

于 2018-05-28T16:22:33.850 回答
0
  //STEP (1)
  //Example simulate upload multiple files with chained api calls. In this example the parameters "idFile" and "arrayidFileExample" are helpful.
  //You should create and send this data from view.
  {
    "idFile": "04fe640f6e4w",                                                                        //id first file                          
    "arrayidFileExample": ["04fe640f6e4w","03g5er4g65erg","g0er1g654er65g4er","0g4er4g654reg654re"]  //simulate idFiles array from view
  }


//STEP (2)
//your upload files api
app.post('/upload', function(req, res) {

    //Express headers, no important in this code
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");


    let arrayIdFiles = req.body.arrayidFileExample;       //create arrayIdFiles

    let isBlock = false;                                  //flag to block call loop to api
    let countIndex = 0;
    let currentIndex = 0;

    //STEP (3)
    //If "arrayIdFiles" index is not exist, set isBlock to true. Remeber flag to block call loop to api
    for(let count in arrayIdFiles) {
        if(req.body.idFile == arrayIdFiles[count]) {
            console.log("current index --> ", countIndex)
            countIndex++;
            console.log("next index --> ", countIndex)
            if(arrayIdFiles[countIndex] == undefined) {
                isBlock = true;
            }
            break;
        }
        countIndex++;
        currentIndex++;
    }

    //STEP (4)
    //If isBlock is equal false, call get upload api with next idFile. this is simulate "recursive api loop"
    if(isBlock == false) {
        postUploadFile(
          'http://localhost:3500/upload',
          {
            "idFile":arrayIdFiles[currentIndex + 1], //send next idFile from arrayIdFiles
            "arrayidFileExample": arrayIdFiles       //initial arrayIdFiles
          });
    }

    //STEP (6)
    //response json example
    const json = JSON.stringify({
    error:false,
    statusCode: 200,
    body:{
        message:'current id file '+req.body.idFile,
    }
    });

    res.write(json);
    return res.end();
});

    //STEP (5)
    //call "/upload" api post
const postUploadFile = (url = '', body = {}) => {
    return new Promise((resolve, reject)=>{
      axios.post(url, body).then(response => {
          return resolve(response.data);
      }).catch(error => {});
    });
};


//server listen instance
server.listen(3500,() => {
});
于 2018-05-28T16:03:39.767 回答
0

这应该与res.write(). 但我认为它确实取决于您的客户端缓存。

我试过这个,但它在我的 Firefox 中不起作用。

app.get('/test', function(req, res) {
  var count     = 0;
  var interval  = setInterval(function() {
    if (count++ === 100) {
      clearInterval(interval);
      res.end();
    }
    res.write('This is line #' + count + '\n');
  }, 100);
});

在我增加写入频率和数量之后,它似乎起作用了。

所以试试:

router.post('/upload', upload.array('upload_data', multerMaxFiles), (req, res, next) => {
 ////some uploading and processing stuff - works nicely
 res.write(JSON.stringify({ 'message': 'File uploaded successfully.' }));// shown to API client nicely
 console.log("what next? " + utilz.inspect(uploaded_file_paths)) //prints file names on console
 next();
});
于 2018-05-28T15:04:24.703 回答