NodeJs 第十七章 文件上传

这篇具有很好参考价值的文章主要介绍了NodeJs 第十七章 文件上传。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前端上传文件有两种方式

  • 方式一:使用 FormData 发送 ajax 上传
// 创建FormData对象  
var formData = new FormData();    
  
// 添加文件数据  
var fileInput = document.querySelector('input[type="file"]');  
formData.append('file', fileInput.files[0]);  
  
// 创建XMLHttpRequest对象  
var xhr = new XMLHttpRequest();  
  
// 设置请求的配置信息  
xhr.open('POST', 'api/upload', true);  
xhr.send(formData);  
  
// 监听请求的完成事件  
xhr.onload = function() {  
  if (xhr.status === 200) {  
    console.log('上传成功!');  
  } else {  
    console.error('上传失败!');  
  }  
};
  • 方式二:使用 Form 表单上传(需要指定enctype="multipart/form-data")
<form action="/api/upload" method="POST" enctype="multipart/form-data">
  <p>
    <input type="text" name="a" />
  </p>
  <p>
    <input type="file" name="img" />
  </p>
  <p>
    <button>提交</button>
  </p>
</form>

文件上传的两种方式,他们有什么关系?

  1. FormData构造函数,用于创建FormData实例。
  2. 允许通过append()方法向FormData对象添加表单字段和文件数据。
  3. 自动将表单字段和文件数据封装成multipart/form-data格式的请求体,以便通过XMLHttpRequestFetch API发送。
  4. 在发送请求时,会自动将请求的Content-Type头部设置为multipart/form-data

multipart/form-data 是什么?

Multipart/form-data是一种在HTTP传输协议中用于在Web表单中传输文件的编码方式。它是一种灵活的编码方式,能够同时处理表单中的多个字段和文件上传。

multipart/form-data编码中,表单中的每个数据字段都被封装成一个消息体,并以一定的分隔符分隔消息体。这个编码方式使用了类似于multipart/mixed的格式,但主要用于表单数据的传输。每个消息体包含一个字段名称和字段值,以及一个可选的文件上传字段。

当使用multipart/form-data编码方式时,表单数据被封装成一条消息,每个控件对应消息的一部分。这种编码方式支持在提交表单时上传文件,因此被广泛应用于文件上传功能的实现中。

总结来说,multipart/form-data的编码方式是一种将表单中的每个数据字段封装成一个消息体的编码方式,并以一定的分隔符分隔消息体。这种编码方式支持在提交表单时上传文件,并能够处理多个字段和文件上传。

multipart/form-data 实现原理

在form-data编码中,表单数据被封装成一条消息,以标签为单元,用分隔符分开。这意味着表单数据被分割成多个部分,每个部分都以标签开头,以分隔符结尾。这样可以同时上传多个键值对或文件。

当上传文件时,除了普通的键值对数据外,每个文件都会被封装为一个独立的消息部分。每个文件部分都包含一个Content-Type头部,用于指定文件的媒体类型(即文件类型),以及一个Content-Disposition头部,用于描述该文件部分的名称和是否应该被显示或保存。

由于有分隔符隔离每个部分,所以form-data既可以上传键值对,也可以上传文件。同时,由于它采用了键值对的方式,所以可以上传多个文件或键值对。

POST / HTTP/1.1
Content-Length: 551
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="a"

1
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="img"; filename="截屏2024-01-17 10.13.02.png"
Content-Type: <Content-Type header here>

(data)
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="b"

2
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="file"; filename="截屏2024-01-17 16.40.30.png"
Content-Type: <Content-Type header here>

(data)
------WebKitFormBoundary7MA4YWxkTrZu0gW--

上传文件为什么只能是 form-data 类型的请求体?

HTTP请求体主要有以下几种格式:

  • multipart/form-data:主要用于表单数据的提交,特别是文件上传。它会把表单数据封装成一条消息,以标签为单位,用分隔符分开。既可以上传键值对,也可以上传文件。
  • application/x-www-form-urlencoded:会将表单内的数据转换为键值对,用&分隔。当method为get时,会将表单数据编码为(name1=value1&name2=value2…),然后把这个字符串append到url后面,用?分隔。这个格式不能提交文件,区别于multipart/form-data。
  • raw:可以上传任意格式的文本,包括text、json、xml、html等。
  • binary:相当于Content-Type:application/octet-stream,只可以上传二进制数据,用来上传文件。由于没有键值,一次只能上传一个文件。

由此可以看出 application/x-www-form-urlencodedraw,只支持字符串,不支持二进制文件。binarymultipart/form-data都支持二进制文件,但 multipart/form-data可以以键值对的形式进行文件上传,试用起来更灵活。

node 服务如何获取到客户端上传的文件

我们可以借用 Express 官方维护的 multer 中间件文章来源地址https://www.toymoban.com/news/detail-805093.html

const express = require("express");
const multer = require("multer");
const path = require("path");
const app = express();
const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, path.resolve(__dirname, "./public/upload"));
  },
  filename: function (req, file, cb) {
    // 时间戳-6位随机字符.文件后缀
    const timeStamp = Date.now();
    const ramdomStr = Math.random().toString(36).slice(-6);
    const ext = path.extname(file.originalname);
    const filename = `${timeStamp}-${ramdomStr}${ext}`;
    cb(null, filename);
  },
});

const upload = multer({
  storage,
  limits: {
    fileSize: 150 * 1024,
  },
  fileFilter(req, file, cb) {
    //验证文件后缀名
    const extname = path.extname(file.originalname);
    const whitelist = [".jpg", ".gif", "png"];
    if (whitelist.includes(extname)) {
      cb(null, true);
    } else {
      cb(new Error(`your ext name of ${extname} is not support`));
    }
  },
});

app.post("/api/upload", upload.single("img"), (req, res) => {
  const url = `/upload/${req.file.filename}`;
  res.send({
    code: 0,
    msg: "",
    data: url,
  });
});

const port = 5008;
app.listen(port, () => {
  console.log(`server listen on ${port}`);
});

到了这里,关于NodeJs 第十七章 文件上传的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • ArduinoUNO实战-第十七章-火焰传感器

    Arduino火焰传感器(含代码) 火焰传感器与 Arduino 连接 检测到由火源报警 远红外火焰传感器可以用来探测火源或其它一些波长在700纳米~1000纳米范围内的热源,在机器人比赛中,远红外火焰探头起到非常重要的作用,它可以用作机器人的眼睛来寻找火源或足球。利用它可以制作

    2024年01月20日
    浏览(32)
  • 离散数学复习---第十七章 平面图【概念版】

    目录 17.1 平面图的基本概念 17.2  欧拉公式 17.3  平面图的判断 17.4  平面图的对偶图 定义17.1   如果能将无向图G画在平面上使得除顶点外处处无边相交,则称G为 可平面图 ,简称为 平面图 。画出的无边相交的图称为G的 平面嵌入 。无平面嵌入的图称为 非平面图 。 定理17.

    2024年02月05日
    浏览(28)
  • 《微服务实战》 第十七章 Redis下载与安装

    第二十八章 分布式锁框架-Redisson 第二十四章 Spring boot 操作 Redis 第二十三章 Redis RDB AOF 第二十一、二十二章 Redis发布订阅、事务;HyperLoglog基数统计 第二十章 Redis连接指令 客户端指令 服务器指令 第十九章 Redis key 第十八章 Redis查看配置文件和数据类型 第十七章 Redis下载与安

    2024年02月06日
    浏览(27)
  • 第十七章 Unity 预制件prefab(下)

    本章节我们来讲解如何编辑预制体文件。这里介绍三种打开编辑预制件的方式。第一就是通过预制件的实例游戏对象的Inspector检视面板上面的预制件“打开”按钮。 第二就是在Project工程面板中选中预制件文件(Cube.prefab),然后在Inspector检视面板中点击“打开预制件”。 第

    2024年02月04日
    浏览(23)
  • Hotspot源码解析-第十七章-虚拟机万物创建(三)

    分配Java堆内存前,我们先通过两图来了解下C堆、Java堆、内核空间、native本地空间的关系。 1、从图17-1来看,Java堆的分配其实就是从Java进程运行时堆中选中一块内存区域来映射 2、从图17-2,可以看中各内存空间的关系,当然实际的内存区域比这个复杂的多,这里只是概括说

    2024年01月25日
    浏览(27)
  • 【新版系统架构】第十七章-通信系统架构设计理论与实践

    软考-系统架构设计师知识点提炼-系统架构设计师教程(第2版) 第一章-绪论 第二章-计算机系统基础知识(一) 第二章-计算机系统基础知识(二) 第三章-信息系统基础知识 第四章-信息安全技术基础知识 第五章-软件工程基础知识(一) 第五章-软件工程基础知识(需求工

    2024年02月15日
    浏览(33)
  • Go学习第十七章——Gin中间件与路由

    Gin框架允许开发者在处理请求的过程中,加入用户自己的钩子(Hook)函数。这个钩子函数就叫中间件,中间件适合处理一些公共的业务逻辑,比如登录认证、权限校验、数据分页、记录日志、耗时统计等 即比如,如果访问一个网页的话,不管访问什么路径都需要进行登录,

    2024年02月07日
    浏览(35)
  • 【Rust】Rust学习 第十七章Rust 的面向对象特性

    面向对象编程(Object-Oriented Programming,OOP)是一种模式化编程方式。对象(Object)来源于 20 世纪 60 年代的 Simula 编程语言。这些对象影响了 Alan Kay 的编程架构中对象之间的消息传递。他在 1967 年创造了  面向对象编程  这个术语来描述这种架构。关于 OOP 是什么有很多相互矛

    2024年02月11日
    浏览(32)
  • TCP/IP网络编程 第十七章:优于select的epoll

    select复用方法其实由来已久,因此,利用该技术后,无论如何优化程序性能也无法同时接入上百个客户端(当然,硬件性能不同,差别也很大)。这种select方式并不适合以Web服务器端开发为主流的现代开发环境,所以要学习Linux平台下的epoll。 基于select的I/O复用技术速度慢的原

    2024年02月16日
    浏览(27)
  • 30天精通Nodejs--第十七天:express-路由配置

    上篇文章我们简单介绍了express的基础用法,包括express的安装、创建路由及项目启动,对express有了一个基础的了解,这篇开始我们将详细介绍express的一些高级用法。 本篇文章介绍express的路由配置的用法。 上篇文章中我们在hello world中写了一个简单的get请求,除了get请求方式

    2024年01月22日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包