如何确保文件已下载,然后 return 对客户端的响应?
How to make sure that the file is downloaded and then return a response to client side?
我必须使用 nodejs 下载 json 文件并做出反应。
所以,当用户点击下载按钮时,一个请求被发送到 nodejs,然后我发出一个 http 请求传递给用户,传递,然后 url 在服务器上下载 json 文件然后下载这个文件在客户端
服务器端的文件下载需要将近 5 分钟,问题是我在下载文件完成之前遇到网络错误:
GET http://127.0.0.1:4000/downloadFile net::ERR_EMPTY_RESPONSE
Error: Network Error
at createError (createError.js:17)
at XMLHttpRequest.handleError (xhr.js:80)
当点击下载按钮时,反应端的这个函数被调用:
downloadFile() {
this.setState({ buttonDownloadText: 'Wait ...' })
axios.get(process.env.REACT_APP_HOST + '/downloadFile')
.then(resp => {
window.open(process.env.REACT_APP_HOST + '/download?namefile=' + resp.data.fileName, '_self')
this.setState({ buttonDownloadText: 'Start download' })
})
.catch((error) => {
console.log(error) //here is where the Network Error is returned
this.setState({ buttonDownloadText: 'Error. Try again' })
})
}
服务器端:
const http = require('http');
const fs = require('fs');
app.get('/downloadFile', function (req, res, next) {
try {
const headers = new Headers();
const URL = env.URL_API + '/api/downloadFile'
const DOWNLOADURL = env.URL_API + '/api/download'
headers.set('Authorization', 'Basic ' + base64.encode(username + ":" + password));
fetch(URL, {
method: 'GET',
headers: headers,
})
.then(r => r.json())
.then(data =>
fetch(DOWNLOADURL + '/' + data.fileName, {
method: 'GET',
headers: headers,
}).then(result => {
const url = 'http://user:pass@url' + data.fileName
const arq = __dirname + '/download/' + data.fileName
var file = fs.createWriteStream(arq);
http.get(url, function (response) {
response.pipe(file);
file.on('finish', () => file.close(() => res.status(200).send({ file: data.fileName });)) //I have to return the file name to react function
});
}).catch(error => {
logger.error(`${error}`);
})
})
.catch(error => {
logger.error(`${error.status || 500} - ${error} - ${req.originalUrl} - ${req.method} - ${req.ip}`);
res.sendStatus(500)
})
....
});
downloadFile
函数必须 return 文件名,所以我调用下载路由在 clint 端进行下载
app.get('/download', function (req, res) {
try {
const file = __dirname + '/download/' + req.query.namefile;
res.download(file);
} catch (error) {
logger.error(`${error.status || 500} - ${error} - ${req.originalUrl} - ${req.method} - ${req.ip}`);
}
});
所以,我的意思是,为什么我的 downloadFile
路由没有等待下载文件完成 return res.status(200).send({ file: data.fileName })?
由于不能强制浏览器等待服务器的长时间响应,我建议采用不同的方法:将文件上传到云端(例如 AWS 或 Firebase),然后 return link给客户。
如果使用 Firebase(或其他实时数据库),服务器可以在文件上传完成时在数据库中设置一个标志。因此,当文件可供下载时,客户端会收到异步通知。
我必须使用 nodejs 下载 json 文件并做出反应。 所以,当用户点击下载按钮时,一个请求被发送到 nodejs,然后我发出一个 http 请求传递给用户,传递,然后 url 在服务器上下载 json 文件然后下载这个文件在客户端
服务器端的文件下载需要将近 5 分钟,问题是我在下载文件完成之前遇到网络错误:
GET http://127.0.0.1:4000/downloadFile net::ERR_EMPTY_RESPONSE
Error: Network Error
at createError (createError.js:17)
at XMLHttpRequest.handleError (xhr.js:80)
当点击下载按钮时,反应端的这个函数被调用:
downloadFile() {
this.setState({ buttonDownloadText: 'Wait ...' })
axios.get(process.env.REACT_APP_HOST + '/downloadFile')
.then(resp => {
window.open(process.env.REACT_APP_HOST + '/download?namefile=' + resp.data.fileName, '_self')
this.setState({ buttonDownloadText: 'Start download' })
})
.catch((error) => {
console.log(error) //here is where the Network Error is returned
this.setState({ buttonDownloadText: 'Error. Try again' })
})
}
服务器端:
const http = require('http');
const fs = require('fs');
app.get('/downloadFile', function (req, res, next) {
try {
const headers = new Headers();
const URL = env.URL_API + '/api/downloadFile'
const DOWNLOADURL = env.URL_API + '/api/download'
headers.set('Authorization', 'Basic ' + base64.encode(username + ":" + password));
fetch(URL, {
method: 'GET',
headers: headers,
})
.then(r => r.json())
.then(data =>
fetch(DOWNLOADURL + '/' + data.fileName, {
method: 'GET',
headers: headers,
}).then(result => {
const url = 'http://user:pass@url' + data.fileName
const arq = __dirname + '/download/' + data.fileName
var file = fs.createWriteStream(arq);
http.get(url, function (response) {
response.pipe(file);
file.on('finish', () => file.close(() => res.status(200).send({ file: data.fileName });)) //I have to return the file name to react function
});
}).catch(error => {
logger.error(`${error}`);
})
})
.catch(error => {
logger.error(`${error.status || 500} - ${error} - ${req.originalUrl} - ${req.method} - ${req.ip}`);
res.sendStatus(500)
})
....
});
downloadFile
函数必须 return 文件名,所以我调用下载路由在 clint 端进行下载
app.get('/download', function (req, res) {
try {
const file = __dirname + '/download/' + req.query.namefile;
res.download(file);
} catch (error) {
logger.error(`${error.status || 500} - ${error} - ${req.originalUrl} - ${req.method} - ${req.ip}`);
}
});
所以,我的意思是,为什么我的 downloadFile
路由没有等待下载文件完成 return res.status(200).send({ file: data.fileName })?
由于不能强制浏览器等待服务器的长时间响应,我建议采用不同的方法:将文件上传到云端(例如 AWS 或 Firebase),然后 return link给客户。
如果使用 Firebase(或其他实时数据库),服务器可以在文件上传完成时在数据库中设置一个标志。因此,当文件可供下载时,客户端会收到异步通知。