比如前端有一个文件上传的功能

<div>
<input type="file">
<button>开始上传</button>
</div>
<script>
const btn = document.querySelector('button');
btn.onclick = async()=>{
const fileInput = document.querySelector('input'); // 拼接参数
const formData = new FormData();
formData.append('file', fileInput.files[0]); // 开始上传
const res = await fetch('/upload',{method: 'POST', body: formData}).then(res=>res.json());
console.log(res);
}
</script>

如果后端是nodejs原生写的一个服务,改如何处理接收呢?

简单处理

我们可以这样做

import { createServer } from "http";
import path from 'path';
import { __dirname } from './utils/index.js'
import fs from 'fs' const httpServer = createServer((req, res) => {
const { url } = req;
if (url === '/upload') {
console.log('开始上传'); let body = '';
req.on("data", (chunk) => {
console.log("上传中");
body += chunk;
}) req.on("end", () => {
const recFile = path.join(__dirname, '../a.png');
fs.writeFile(recFile, body, 'binary', (err) => {
console.log("上传完成");
if (!err) {
res.end("sucess")
}
})
})
} }); // 创建一个http服务
httpServer.listen(3000, () => console.log('服务已经启动: http://127.0.0.1:3000')); // 启动http服务

那一个图片传入举例,我们会发现图片确实被存储到项目中。

但是紧接着我们就会发现,图片打不开!

强制使用记事本或者开发工具以编码形式打开看看 会发现内部文件类似于这样的

------WebKitFormBoundarye8NwBtLb3tKGD502
Content-Disposition: form-data; name="file"; filename="jd.jpg"
Content-Type: image/jpeg ÿØÿàJFIFÿÛCÿÛCÿM"ÿÄ
ÿÄ. "#$%!&'45ÿÿÄ>!1"A2Q#aq
����
ÿØÿàJFIFÿÛCÿÛCÿM"ÿÄ
ÿÄ. "#$%!&'45ÿÿÄ>!1"A2Q#aq
------WebKitFormBoundarye8NwBtLb3tKGD502--

我们来解析一下这里边的结构

其中数据边界描述和文件的其他信息 在请求头里 浏览器也帮我们加上了这些属性。和传入后端的body内部保持一致



boundary即为数据边界描述的意思,文件上传时内容是分段传输的,每一boundary表示一个fild(form表单控值)边界,用于可能存在的分段上传。

分析原因

上一步我们已经分析了接收到的数据,

通过分析body我们得知:body数据多了一些和文件二进制本身无关的其他信息。

那么处理起来就很简单了,我们只需要把这些无用信息去除即可。

最后再将蓝色部分的纯文件二进制写入到文件即可。

处理办法

if (url === '/upload') {
req.setEncoding('binary'); // 将传入的文件设为二进制编码(若本身为二进制,此步可省) // 边界字符串
var boundary = req.headers['content-type'].split('; ')[1].replace('boundary=', ''); let body = ''; // 请求体(前端post传入的所有参数内容)
req.on('data', function (chunk) { body += chunk; }); let fileName = ''; // 文件名
req.on('end', function () {
// 处理前端传入的二进制数据,格式化成json
const file = querystring.parse(body, '\r\n', ':'); //通过Content-Disposition来获取文件相关信息
const fileCtd = file['Content-Disposition'].split('; ');
for (const value in fileCtd) {
if (fileCtd[value].indexOf("filename=") != -1) {
fileName = fileCtd[value].substring(10, fileCtd[value].length - 1);
if (fileName.indexOf('\\') != -1) {
fileName = fileName.substring(fileName.lastIndexOf('\\') + 1);
}
}
} // 获取文件类型
const fileType = file['Content-Type']; var entireData = body.toString(); // var contentTypeRegex = /Content-Type: image\/.*/;
const contentType = file['Content-Type'].substring(1); // --===提取只包含文件本身二进制数据,去除前后的其它内容 start===--
// 1. 移除前置多余字符:根据contentType字段来定位
var upperBoundary = entireData.indexOf(contentType) + contentType.length;
var shorterData = entireData.substring(upperBoundary);
console.log(upperBoundary);
console.log(shorterData);
// 2. 替换开始位置的空格
var binaryDataAlmost = shorterData.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
// 3. 移除后置多余字符:根据 "--"+ boundary + "--" 来定位
var binaryData = binaryDataAlmost.substring(0, binaryDataAlmost.indexOf('--' + boundary + '--'));
// --===提取只包含文件本身二进制数据,去除前后的其它内容 end===-- // 保存文件
fs.writeFile(fileName, binaryData, 'binary', (err) => {
res.end('图片上传完成');
});
});
}

参考这篇文章:我的另一篇文章

nodejs接收前端传入的文件的更多相关文章

  1. python取出前端传入execl文件中的数据

    from openpyxl import load_workbook #获取前台传入的文件 uploadedFile = request.FILES.get('file') #获取execl文件 wb ...

  2. nodejs接收前端formData数据

    转:https://www.cnblogs.com/zhensg123/p/11078579.html 很多时候需要利用formdata数据格式进行前后端交互. 前端代码可以是如下所示: <!D ...

  3. 【转】nodejs接收前端formData数据

    很多时候需要利用formdata数据格式进行前后端交互. 前端代码可以是如下所示: <!DOCTYPE html> <html lang="en"> < ...

  4. 【springmvc】之使用jQuery接收前端传入List对象

    前端代码: <form id="person_add" method="post" action="user"> <tab ...

  5. PDF.Js的使用—javascript中前端显示pdf文件

    PDF.Js的使用—javascript中前端显示pdf文件 写于2018/12/6 起因是一个图片展示页面需要展示pdf格式的文件,所以查了半天决定使用pdf.js,我也不求有多了解它,能实现我想要 ...

  6. springboot接收前端传参的几种方式

    1.通过HttpServletRequest接收,常用于获取请求头参数以及Cookie,适用于GET 和 POST请求方式,以下两种方式: @GetMapping("/demo1" ...

  7. 前端js,css文件合并三种方式,bat命令

    前端js,css文件合并三种方式,bat命令 前端js文件该如何合并三个方式如下:1. 一个大文件,所有js合并成一个大文件,所有页面都引用它.2. 各个页面大文件,各自页面合并生成自己所需js的大文 ...

  8. form表单提交,Servlet接收并读取Excel文件

    首先是jsp页面: <body scroll=no style="overflow-y:hidden;" onselectstart="return false&q ...

  9. nodejs 接收上传的图片

    1.nodejs接收上传的图片主要是使用formidable模块,服务器是使用的express搭建. 引入formidable var formidable = require('./node_mod ...

  10. SpringMVC接收前端传值有哪些方式?

    有很多种,比如: 1.通过@RequestParam注解接收请求参数: 2.通过Bean封装,接收多个请求参数 3.通过@ModelAttribute绑定接收前端表单数据 4.通过@PathVaria ...

随机推荐

  1. Mybatis的原始的执行方式

    一.通过SqlSessionFactory创建sqlsession,再由Sqlsession获取session对象,然后通过session中的执行器Executor,去执行MapperStatemen ...

  2. 康谋分享 | aiSim5仿真场景重建感知置信度评估(三)

    aiSim5重建高精度的真实交通场景,用于测试和训练ADAS/AD系统.内置场景包括赛道.车库.高速公路和城市环境.通过全局行动日志,aiSim能将驾驶数据转化为场景重建.车道线检测算法在仿真与现实世 ...

  3. 2024dsfzB层考试总结

    2024B层次十一集训 10.3日 数据结构专题模拟 考试总结 FrankWKD Updated AT 2024/10/3 13:21 概述 总分:\(140/400\) Rank:\(24/87\) ...

  4. 网鼎杯-nmap

    Web 0x01 nmap 查看源码提示: 研究了半天分隔符绕过,后来放弃了,根据题目提示(127.0.01,不用扫外网),尝试扫描/flag并尝试将其输出到1.txt中 -iL /flag -oN ...

  5. Docker自定义镜像输出日志

    概述 本文主要解决Docker自定义镜像之后,通过docker logs命令查看不到相关日志的问题 在 Docker 中自定义镜像输出日志,通常需要确保你的应用程序将日志输出到 标准输出(stdout ...

  6. SQL 日常练习 (十四)

    最近的项目都比较忙, 没太有时间来做练习, 不过 sql 这块, 还是始终要保持良好的手感, 我已经渐渐感觉到, 随着写得越来越多, 当然不只是在这里, 更多是在工作中, 不过涉及信息安全不能共享. ...

  7. Tableau 我常用函数整理

    日期函数 dateadd datedadd (date_part, interval, date) 表示在日期 date 的基础上, 以date_part 为单位, 与之间隔 interval的日期 ...

  8. Flutter图片组件的定制开发与配置实践

    @charset "UTF-8"; .markdown-body { line-height: 1.75; font-weight: 400; font-size: 15px; o ...

  9. 从零开始,打造一款属于自己的JavaScript编程语言

    @charset "UTF-8"; .markdown-body { line-height: 1.75; font-weight: 400; font-size: 15px; o ...

  10. js操作session

    // 保存数据到sessionStorage sessionStorage.setItem('key', 'value'); // 从sessionStorage获取数据 sessionStorage ...