我希望在向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
答案 0 :(得分:1)
一旦您将响应发送回浏览器(为了防止在长时间处理期间超时),该http请求就完成了。您无法再发送任何数据,尝试这样做会触发服务器端错误。你不能"连锁路线"您似乎想要这样做的方式,因为一旦您发送了第一个回复,您就无法通过该http请求发送更多数据。
有两种常见的方法可以解决这个问题。
作为初始响应的一部分,发回一个事务ID,然后让客户端每隔几秒钟回调一次Ajax调用,询问该事务的最终状态。服务器可以返回"正在进行中"直到它最终完成然后它才能返回最终状态。
您可以将webSocket或socket.io连接从客户端连接到服务器。作为对上传的初始响应的一部分,发回一个交易ID。然后,当事务在服务器端完成时,它会在具有最终状态的transactionID的特定客户端的webSocket或socket.io连接上发送通知。然后,客户可以相应地响应该最终状态。您可以打开webSocket / socket.io连接以与其他请求一起使用,也可以关闭该连接。
使用这两种技术,您还可以返回/发送客户端可用于显示完成进度的进度值(如完成百分比)。这通常对客户端非常有帮助,以防止不耐烦的用户放弃或刷新页面。如果他们可以看到处理正在进行,他们就不会放弃思考它可能会停止工作。
答案 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,() => {
});