发送API响应后,在NodeJ中链接路由值

时间:2018-05-28 14:34:03

标签: javascript node.js express multer

我希望在向end-ser发送API响应后将NodeJs中的路由与值链接起来

为什么:>上传的文件有点大(每个5-50mb)并且需要一些处理,当我的NodeJS代码工作时无法让我的API用户等待/超时..所以需要,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 Baua

3 个答案:

答案 0 :(得分:1)

一旦您将响应发送回浏览器(为了防止在长时间处理期间超时),该http请求就完成了。您无法再发送任何数据,尝试这样做会触发服务器端错误。你不能"连锁路线"您似乎想要这样做的方式,因为一旦您发送了第一个回复,您就无法通过该http请求发送更多数据。

有两种常见的方法可以解决这个问题。

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

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

  3. 使用这两种技术,您还可以返回/发送客户端可用于显示完成进度的进度值(如完成百分比)。这通常对客户端非常有帮助,以防止不耐烦的用户放弃或刷新页面。如果他们可以看到处理正在进行,他们就不会放弃思考它可能会停止工作。

答案 1 :(得分:0)

这适用于res.write()。但它确实取决于你的客户缓存。

我尝试了this,但它在我的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();
});

答案 2 :(得分: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,() => {
});