如何跟踪上传到NodeJs服务器的文件的进度。我在服务器端使用multer上传文件。 ?
我是否需要向客户端发送某种信息,以便客户端获得上传进度或者这是在内部完成的。客户可以跟踪其进度。
以下是我用来上传文件的代码:
var multer = require('multer');
app.use(multer({dest:'./tmp',limits: {fileSize: 4*1024*1024}}).single('upload'));
router.post('/upload',function(req,res){
console.log(req.file);
});
答案 0 :(得分:3)
这是LinusU在项目github页面上的answer(他建议使用progress-stream):
管道要求到那个并给它更多。
var p = progress()
var upload = multer().single('file')
req.pipe(p)
p.headers = req.headers
p.on('progress', _)
upload(p, res, _)
答案 1 :(得分:3)
工作代码
使用挂钩的REACTJS代码(前端)
upload.js 或 upload.jsx
import React, { useState } from "react";
import Axios from "axios";
import { Progress } from "reactstrap";
const Upload = () => {
const [uploadPercentage, setUploadPercentage] = useState(0);
const [showProgressBar, setProgressBarVisibility] = useState(false);
const onSubmit = e => {
e.preventDefault();
setProgressBarVisibility(true);
const demo = document.getElementById("demo");
const bodyFormData = new FormData(demo);
Axios({
headers: {
"Content-Type": "multipart/form-data",
},
method: "POST",
data: bodyFormData,
url: "/profile", // route name
baseURL: "http://localhost:5000/api/upload", //local url
onUploadProgress: progress => {
const { total, loaded } = progress;
const totalSizeInMB = total / 1000000;
const loadedSizeInMB = loaded / 1000000;
const uploadPercentage = (loadedSizeInMB / totalSizeInMB) * 100;
setUploadPercentage(uploadPercentage.toFixed(2));
console.log("total size in MB ==> ", totalSizeInMB);
console.log("uploaded size in MB ==> ", loadedSizeInMB);
},
encType: "multipart/form-data",
});
};
const handleFormClick = () => {
setProgressBarVisibility(false);
setUploadPercentage(0);
};
return (
<div>
<form onSubmit={e => onSubmit(e)} id="demo">
<input type="file" name="avatar" id="avatar" />
<input type="submit" value="Submit" />
</form>
{showProgressBar ? (
<>
<div className="text-center">
{parseInt(uploadPercentage) !== 100
? `Upload percentage - ${uploadPercentage}`
: "File successfully uploaded"}
</div>
<Progress
animated={parseInt(uploadPercentage) !== 100}
color="success"
value={uploadPercentage}
/>
</>
) : null}
</div>
);
};
export default Upload;
NODEJS代码(后端)
upload.js
const express = require("express");
const multer = require("multer");
const router = express.Router();
var storage = multer.diskStorage({
destination: "./uploads/",
filename: function(req, file, cb) {
cb(null, file.originalname);
},
});
const upload = multer({ storage });
router.post("/profile", upload.single("avatar"), function(req, res, next) {
console.log(req.file);
if (req.file) {
return res.status(200).json(req.file);
}
return res.status(400).json({ msg: "PLEASE UPLOAD FILE" });
});
module.exports = router;
答案 2 :(得分:0)
反应前端
const formData = new FormData();
formData.append('myImage', this.state.imageData);
const config = {
onUploadProgress: progressEvent => console.log(progressEvent.loaded), // TO SHOW UPLOAD STATUS
headers: {
'content-type': 'multipart/form-data'
}
};
axios.post("/api/api/save-media", formData, config)
.then((response) => {
// do whatever you want
}).catch((error) => {
console.log(error)
});
答案 3 :(得分:0)
在跟踪文件上传进度时,Multer不太灵活。 我已经尝试了很多方法,使用progress-stream库传递请求,使用我自己的函数来计算百分比,然后将进度流式传输到socket.io等。 使用socket.io的方法(将百分比流式传输到套接字,然后再返回到客户端)在一定程度上可行,但是主要的问题是Multer在文件上传到服务器之前不会返回执行控制权, 因此,如果您将其设置为类似以下的中间件功能:
this.router.post('/upload', upload.single('file'), function(req: Request, res: Response) {...}
您根本无法获取进度或req.file(如果您尝试在上载之前添加中间件,例如this.router.post('/ upload',要做些什么,upload.single('file' )...),因为那时req.file将不存在,然后,当您尝试访问req.file时,它将是100%。这就是中间件的工作方式。 如果您需要跟踪进度,但又不将其发送回客户端(如果需要进度条,则不是这种情况),则可以执行以下操作。 但!这将起作用,因为您将计算请求大小,而不是req.file大小(req.file仅存在于Multer的上下文中) 并不是很大的不同,req和req.file出现在同一请求中,因此,如果使用下面的代码,您将看到百分比,然后将运行用于使用Multer保存文件的代码。 跟踪服务器大小进度的示例如下:
var uploadImages = multer({ dest: ...}).single('...');
//more code ...
this.router.post('/upload', (req: Request, res: Response) => {
let progress = 0;
let fileSize = req.headers['content-length'] ? parseInt(req.headers['content-length']) : 0;
req.on('data', (chunk) => {
progress += chunk.length;
res.write((`${Math.floor((progress * 100) / fileSize)} `));
if (progress === fileSize) {
console.log('Finished', progress, fileSize)
}
});
})
//And calling the Multer function down here...
uploadImages(req,res...){}
在Multer的文档中指定了调用中间件功能来使用Multer上传文件,而不是在路由声明中使用该文件(在该文件中显示为“错误处理”)。 “如果您想专门从Multer中捕获错误,则可以自己调用中间件功能。”
req.file的值仅在数据到达Multer进行处理和保存的上下文中存在。 因此,对于任何想提出一种在服务器端侦听进度的方法的人,我建议,如果可以的话,并且需要在前端进行,您可以使用Axios,它具有非常好的跟踪进展情况,以实现承诺。
发送表单数据并跟踪进度的示例:
saveFile(file,url): Promise<...> {
let formData = new FormData();
formData.append('file', file);
const config = {
onUploadProgress: (progressEvent) => {
var percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total)
//do something with the percentCompleted
//I used an observable to pass the data to a component and subscribed to it, to fill the progressbar
}
}
return axios.post(url, formData, config)
}
希望它能满足您的需求,并帮助您避免头痛。
答案 4 :(得分:0)
您可以简单地使用中间件来跟踪文件上传的进度。
我们在multer的中间件之前使用这个中间件。
通过这个中间件,我们为 req 对象设置了一个事件监听器来跟踪上传进度。然后我们调用next来调用下一个中间件(Multer)。
代码如下:
const multer = require('multer');
const upload = multer({dest:'./tmp',limits: {fileSize: 4*1024*1024}});
function progress_middleware(req, res, next){
let progress = 0;
const file_size = req.headers["content-length"];
// set event listener
req.on("data", (chunk) => {
progress += chunk.length;
const percentage = (progress / file_size) * 100;
// other code ...
});
// invoke next middleware
next();
}
router.post('/upload', progress_middleware, upload.single('upload'), (req,res) => {
console.log(req.file);
});