文件上传-boundary的作用
文件上传中boundary 分隔符,到底起到什么作用? 基于node搭建服务,一步一步进行拆解
http文件上传
错误的方式
启动服务的服务,可以通过接口调试工具 ApiPost
,或者通过浏览器input表单上传的方式。
导入http对象、以及fs模块。
- 通过
req.setEncoding("binary")
将字符集设置成 二进制,,这样得到的数据就不是 buffer 对象而是 ASCII 编码后的字符串,方便控制台阅读,以及通过一些字符串的方法来正确的处理数据了。 - 创建一个
writeStream
的写入流,并保存文件到当前文件下。(ps:这里文件的名称随便取的,后面可以借助框架来出来) - 监听
data
数据读取,将入数据写入到流中。 - 最后查看写入地址的图片,是否能正常显示???
答案是:No
点击图片,或者通过图片编辑器打开文件。乱码
通过console.log(data);
输出一堆乱码
const server = http.createServer((req, res) => {
req.setEncoding("binary");
const ws = fs.createWriteStream("./就是干.png", { flags: "a+" });
let currentSize = 0;
req.on("data", (data) => {
console.log(data);
ws.write(data);
});
req.on("end", () => {
ws.close();
res.end(JSON.stringify({ code: 0, message: "upload file sucess" }));
});
});
正确的方式
首先如何去解决这个问题,文件打开是乱码,日志打开是乱码。。。 不过我们还可以在要打印请求数据的地方打上断点,通过 debugger 的模式来运行代码:
点击 “运行和调试” 后,vs code 就会帮我们把服务器运行起来了:
之后当我们发送了上传的请求,再点击下图右上角的 “单步跳过”,就可以看到请求的数据了 —— 那些可以被 ASCII 编译的信息,比如英文字母,可以直接看到了,而图片的数据则是一堆乱码:
尝试的去除 数据分割符号、表单项名称、表单的值等数据,将里面的图片数据截取出来然后通过写入流生成图片。
- 获取
boundary
,注意字符串切割的时候空格 - 将文件转为 二进制文件
- 在写入流写入完成后,对文件进行统一的截取处理。
第一步、获取 boundary分隔符
--------------------------292065587859058158508879
----WebKitFormBoundaryxshl9CtTBRH1BvBI
boundary
分隔符不是固定形式的,这取决于访问该数据的端口,服务器会返回不同的类型。
const boundary = req.headers["content-type"]
.split("; ")[1]
.replace("boundary=", "");
console.log(boundary);
第二步 在写入流写入完成后,对文件进行统一的截取处理。
req.on("end", () => {
// 统一对文件进行处理
// 这里预设的文件类型是 png类型
const imageType = "image/png";
const imageTypePosition = formData.indexOf(imageType) + imageType.length;
let imageData = formData.substring(imageTypePosition);
// 过滤空格
imageData = imageData.replace(/^\s\s*/, "");
// 替换boundary 风格符号, 会添加 --***--
imageData = imageData.substring(0, imageData.indexOf(`--${boundary}--`));
fs.writeFile("./foo.png", imageData, "binary", () => {
res.end("file upload end");
});
});
最终效果图
express文件上传
当然我们在正常的开发流程中,一般不会基于原生的http
的方式进行开发。下面我们在 express
框架中使用相关的插件 multer
来快速的实现文件的上传。
npm i express multer
- 通过
express
创建一个 app 的对象,并对端口3000进行监听 - 通过
multer
插件,创建一个upload 的中间件 - 通过
multer
插件中提供的方法,设置 文件的后缀名称 - 并且 返回了改文件的一系列参数字段等,如:filename、size、encoding编码格式等,这里就解释了刚刚使用http方式,控制台输出的时候是乱码,编译器默认的编码格式是 utf-8。而改图片是encoding: '7bit',
注意事项: 指定写入的文件夹 不会自动创建,需要手动创建.
const upload = multer({
storage: multer.diskStorage({
destination(req, file, callback) {
callback(null, "./uploads");
},
filename(req, file, callback) {
callback(null, Date.now() + "_" + file.originalname);
},
}),
});
const app = express();
// 单文件上传
app.post("/upload", upload.single("photo"), (req, res, next) => {
console.log(req.file);
res.end("upload file sucess");
});
koa文件上传
最后我们通过 koa 这个框架来实现文件的上传,基本跟express框架的方式类似。
- 通过 koa 创建 app对象,并对端口3000 进行监听
- 通过
koa/multer
创建 upload 中间件。
const upload = multer({
storage: multer.diskStorage({
destination(req, file, cb) {
// 注意这个地方得有对应的文件夹
cb(null, "./uploads");
},
filename(req, file, cb) {
cb(null, Date.now() + "_" + file.originalname);
},
}),
});
const app = new Koa();
uploadRouter.post("/", upload.single("photo"), (ctx, next) => {
console.log(ctx.request.file);
ctx.body = "avator upload sucess";
});
效果图
转载自:https://juejin.cn/post/7241115614101291064