node 文件上传接口的转发的实现(2)

POST / HTTP/1.1 Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryoMwe4OxVN0Iuf1S4 Origin: :3000 Referer: :3000/upload Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36 ------WebKitFormBoundaryoqBx9oYBhx4SF1YQ Content-Disposition: form-data; :3000 ------WebKitFormBoundaryoMwe4OxVN0Iuf1S4 Content-Disposition: form-data;; filename="IMG_9429.JPG" Content-Type: image/jpeg ����JFIF��C // 文件的二进制数据 …… --------WebKitFormBoundaryoMwe4OxVN0Iuf1S4--

根据 WebKitFormBoundaryoMwe4OxVN0Iuf1S4 可以分割出文件的二进制内容

原生 node

使用原生的 node 写一个文件上传的 demo

const http = require("http"); const fs = require("fs"); const util = require("util"); const querystring = require("querystring"); //用http模块创建一个http服务端 http .createServer(function(req, res) { if (req.url == "/upload" && req.method.toLowerCase() === "get") { //显示一个用于文件上传的form res.writeHead(200, { "content-type": "text/html" }); res.end( '<form action="/upload" enctype="multipart/form-data" method="post">' + '<input type="file" multiple="multiple" />' + '<input type="submit" value="Upload" />' + "</form>" ); } else if (req.url == "/upload" && req.method.toLowerCase() === "post") { if (req.headers["content-type"].indexOf("multipart/form-data") !== -1) parseFile(req, res); } else { res.end("pelease upload img"); } }) .listen(3000); function parseFile(req, res) { req.setEncoding("binary"); let body = ""; // 文件数据 let fileName = ""; // 文件名 // 边界字符串 ----WebKitFormBoundaryoMwe4OxVN0Iuf1S4 const boundary = req.headers["content-type"] .split("; ")[1] .replace("boundary=", ""); req.on("data", function(chunk) { body += chunk; }); req.on("end", function() { const file = querystring.parse(body, "\r\n", ":"); // 只处理图片文件; if (file["Content-Type"].indexOf("image") !== -1) { //获取文件名 var fileInfo = file["Content-Disposition"].split("; "); for (value in fileInfo) { if (fileInfo[value].indexOf("filename=") != -1) { fileName = fileInfo[value].substring(10, fileInfo[value].length - 1); if (fileName.indexOf("\\") != -1) { fileName = fileName.substring(fileName.lastIndexOf("\\") + 1); } console.log("文件名: " + fileName); } } // 获取图片类型(如:image/gif 或 image/png)) const entireData = body.toString(); const contentTypeRegex = /Content-Type: image\/.*/; contentType = file["Content-Type"].substring(1); //获取文件二进制数据开始位置,即contentType的结尾 const upperBoundary = entireData.indexOf(contentType) + contentType.length; const shorterData = entireData.substring(upperBoundary); // 替换开始位置的空格 const binaryDataAlmost = shorterData .replace(/^\s\s*/, "") .replace(/\s\s*$/, ""); // 去除数据末尾的额外数据,即: "--"+ boundary + "--" const binaryData = binaryDataAlmost.substring( 0, binaryDataAlmost.indexOf("--" + boundary + "--") ); // console.log("binaryData", binaryData); const bufferData = new Buffer.from(binaryData, "binary"); console.log("bufferData", bufferData); // fs.writeFile(fileName, binaryData, "binary", function(err) { // res.end("sucess"); // }); fs.writeFile(fileName, bufferData, function(err) { res.end("sucess"); }); } else { res.end("reupload"); } }); }

通过 req.setEncoding("binary"); 拿到图片的二进制数据。可以通过以下两种方式处理二进制数据,写入文件。

fs.writeFile(fileName, binaryData, "binary", function(err) { res.end("sucess"); });

fs.writeFile(fileName, bufferData, function(err) { res.end("sucess"); });

koa

在 koa 中使用 koa-body 可以通过 ctx.request.files 拿到上传的 file 对象。下面是例子。

'use strict'; const Koa = require('koa'); const app = new Koa(); const router = require('koa-router')(); const koaBody = require('../index')({multipart:true}); router.post('/users', koaBody, (ctx) => { console.log(ctx.request.body); // => POST body ctx.body = JSON.stringify(ctx.request.body, null, 2); } ); router.get('https://www.jb51.net/', (ctx) => { ctx.set('Content-Type', 'text/html'); ctx.body = ` <!doctype html> <html> <body> <form action="https://www.jb51.net/" enctype="multipart/form-data" method="post"> <input type="text" placeholder="username"><br> <input type="text" placeholder="tile of film"><br> <input type="file" multiple="multiple"><br> <button type="submit">Upload</button> </body> </html>`; }); router.post('https://www.jb51.net/', koaBody, (ctx) => { console.log('fields: ', ctx.request.body); // => {username: ""} - if empty console.log('files: ', ctx.request.files); /* => {uploads: [ { "size": 748831, "path": "/tmp/f7777b4269bf6e64518f96248537c0ab.png", "name": "some-image.png", "type": "image/png", "mtime": "2014-06-17T11:08:52.816Z" }, { "size": 379749, "path": "/tmp/83b8cf0524529482d2f8b5d0852f49bf.jpeg", "name": "nodejs_rulz.jpeg", "type": "image/jpeg", "mtime": "2014-06-17T11:08:52.830Z" } ]} */ ctx.body = JSON.stringify(ctx.request.body, null, 2); } ) app.use(router.routes()); const port = process.env.PORT || 3333; app.listen(port); console.log('Koa server with `koa-body` parser start listening to port %s', port); console.log('curl -i :%s/users -d "user=admin"', port); console.log('curl -i :%s/ -F "source=@/path/to/file.png"', port);

我们来看一下 koa-body 的实现

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/6eae1e350e2c8916832d94a76cbf6ede.html