likes
comments
collection
share

文件上传-boundary的作用

作者站长头像
站长
· 阅读数 12

文件上传中boundary 分隔符,到底起到什么作用? 基于node搭建服务,一步一步进行拆解

http文件上传

错误的方式

启动服务的服务,可以通过接口调试工具 ApiPost,或者通过浏览器input表单上传的方式。

文件上传-boundary的作用

导入http对象、以及fs模块。

  1. 通过 req.setEncoding("binary") 将字符集设置成 二进制,,这样得到的数据就不是 buffer 对象而是 ASCII 编码后的字符串,方便控制台阅读,以及通过一些字符串的方法来正确的处理数据了。
  2. 创建一个writeStream的写入流,并保存文件到当前文件下。(ps:这里文件的名称随便取的,后面可以借助框架来出来)
  3. 监听 data 数据读取,将入数据写入到流中。
  4. 最后查看写入地址的图片,是否能正常显示???

答案是:No 点击图片,或者通过图片编辑器打开文件。乱码 通过console.log(data); 输出一堆乱码

文件上传-boundary的作用


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 的模式来运行代码:

文件上传-boundary的作用

点击 “运行和调试” 后,vs code 就会帮我们把服务器运行起来了:

文件上传-boundary的作用

文件上传-boundary的作用

之后当我们发送了上传的请求,再点击下图右上角的 “单步跳过”,就可以看到请求的数据了 —— 那些可以被 ASCII 编译的信息,比如英文字母,可以直接看到了,而图片的数据则是一堆乱码:

文件上传-boundary的作用

尝试的去除 数据分割符号、表单项名称、表单的值等数据,将里面的图片数据截取出来然后通过写入流生成图片。

  1. 获取 boundary ,注意字符串切割的时候空格
  2. 将文件转为 二进制文件
  3. 在写入流写入完成后,对文件进行统一的截取处理。

第一步、获取 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");

});

});

最终效果图

文件上传-boundary的作用

express文件上传

当然我们在正常的开发流程中,一般不会基于原生的http的方式进行开发。下面我们在 express框架中使用相关的插件 multer来快速的实现文件的上传。

npm i express multer
  1. 通过 express 创建一个 app 的对象,并对端口3000进行监听
  2. 通过 multer 插件,创建一个upload 的中间件
  3. 通过 multer 插件中提供的方法,设置 文件的后缀名称
  4. 并且 返回了改文件的一系列参数字段等,如:filename、size、encoding编码格式等,这里就解释了刚刚使用http方式,控制台输出的时候是乱码,编译器默认的编码格式是 utf-8。而改图片是encoding: '7bit',

文件上传-boundary的作用

注意事项: 指定写入的文件夹 不会自动创建,需要手动创建.

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框架的方式类似。

  1. 通过 koa 创建 app对象,并对端口3000 进行监听
  2. 通过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";

});

效果图

文件上传-boundary的作用

实例代码