第十八章 Express multer 文件上传

news2024/10/8 19:09:28

本章将学习Express multer 文件上传 ,因为Nest 的文件上传是基于 Express 的中间件 multer 实现的,所以在学习 Nest 文件上传之前,我们先学习下 multer 包

首先先创建 multer-test 文件夹
执行下面代码 创建package.json

npm init -y

1719641865424.png
接着安装 express 和 multer 还有 cors 包:

npm install express multer cors

1719641931393.png
创建index.js 并修改:

const express = require('express')
const multer = require('multer')
const cors = require('cors');

const app = express()
app.use(cors());

const upload = multer({ dest: 'uploads/' })

app.post('/aaa', upload.single('aaa'), function (req, res, next) {
    console.log('req.file', req.file);
    console.log('req.body', req.body);
})

app.listen(5200);

app.use 使用中间件 cors 来处理跨域。
用 multer 处理文件上传,指定保存目录为 uploads/。
接着新建index.html:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://unpkg.com/axios@0.24.0/dist/axios.min.js"></script>
</head>

<body>
    <input id="fileInput" type="file" />
    <script>
        const fileInput = document.querySelector('#fileInput');

        async function formData() {
            const data = new FormData();
            data.set('name', '光');
            data.set('age', 20);
            data.set('aaa', fileInput.files[0]);

            const res = await axios.post('http://localhost:5200/aaa', data);
            console.log(res);
        }

        fileInput.onchange = formData;
    </script>
</body>

</html>

使用FormData + axios 上传文件,指定内容的传输格式 content-type 为 multipart/form-data。
用 node 把 server 跑起来,并且用 http-server 把静态服务跑起来
1719642173152.png
1719642250687.png
游览器访问 http://192.168.100.222:8080/1719642282216.png
接着点击选择文件 上传文件 看游览器的控制台 可以看到发送了请求 此时aaa 请求的 body 是多个 boundary 分隔的格式
1719645151005.png
分隔符是在 Content-Type 指定的
1719645308564.png
这是 form-data 的传输格式
接着我们在控制端可以看到服务端打印了信息
1719645361020.png
服务端多了 uploads 目录,下面就保存着我们上传的文件:
1719645383595.png

我们再实现多文件上传 修改index.js

const express = require('express')
const multer = require('multer')
const cors = require('cors');

const app = express()
app.use(cors());

const upload = multer({ dest: 'uploads/' })

app.post('/aaa', upload.single('aaa'), function (req, res, next) {
    console.log('req.file', req.file);
    console.log('req.body', req.body);
})


app.post('/bbb', upload.array('bbb',2), function (req, res, next) {
    console.log('req.files', req.files);
    console.log('req.body', req.body);
})

app.listen(5200);

再次修改index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://unpkg.com/axios@0.24.0/dist/axios.min.js"></script>
</head>
<body>
    <input id="fileInput" type="file" multiple/>
    <script>
        const fileInput = document.querySelector('#fileInput');

        async function formData2() {
            const data = new FormData();
            data.set('name','光');
            data.set('age', 20);
            [...fileInput.files].forEach(item => {
                data.append('bbb', item)
            })

            const res = await axios.post('http://localhost:5200/bbb', data);
            console.log(res);
        }

        fileInput.onchange = formData2;
    </script>
</body>
</html>

input 标签添加 multiple 属性允许多选。
onchange 的时候取出每个 file,通过 append 方法添加到 bbb 字段
1719647069103.png
可以看到上传的是一个数组,并且 uploads 目录下也多了俩文件
1719647129551.png
接着我们在express 里添加错误中间件,一旦某个中间件出了错,express 就会向后找错误处理中间件来调用,如果没有,那就用默认错误处理中间件,返回 500 响应。

const express = require('express')
const multer = require('multer')
const cors = require('cors');

const app = express()
app.use(cors());

const upload = multer({ dest: 'uploads/' })

app.post('/aaa', upload.single('aaa'), function (req, res, next) {
    console.log('req.file', req.file);
    console.log('req.body', req.body);
})


app.post('/bbb', upload.array('bbb', 2), function (req, res, next) {
    console.log('req.files', req.files);
    console.log('req.body', req.body);
}, function (err, req, res, next) {
    console.log('err', err);
})

app.listen(5200);

接着我们上传超过2个文件:
1719647409711.png
可以看到服务端显示了错误,我们再改造一下即可返回错误信息

const express = require('express')
const multer = require('multer')
const cors = require('cors');

const { MulterError } = multer; 

const app = express()
app.use(cors());

const upload = multer({ dest: 'uploads/' })

app.post('/aaa', upload.single('aaa'), function (req, res, next) {
    console.log('req.file', req.file);
    console.log('req.body', req.body);
})


app.post('/bbb', upload.array('bbb', 2), function (req, res, next) {
    console.log('req.files', req.files);
    console.log('req.body', req.body);
}, function(err, req, res, next) {
    if(err instanceof MulterError && err.code === 'LIMIT_UNEXPECTED_FILE') {
        res.status(400).end('Too many files uploaded');
    }
})

app.listen(5200);

传超过 2 个文件,就会收到服务端的 400 的响应:
1719647746031.png

我们尝试多字段上传

const express = require('express')
const multer = require('multer')
const cors = require('cors');

const { MulterError } = multer; 

const app = express()
app.use(cors());

const upload = multer({ dest: 'uploads/' })

app.post('/aaa', upload.single('aaa'), function (req, res, next) {
    console.log('req.file', req.file);
    console.log('req.body', req.body);
})


app.post('/bbb', upload.array('bbb', 2), function (req, res, next) {
    console.log('req.files', req.files);
    console.log('req.body', req.body);
}, function(err, req, res, next) {
    if(err instanceof MulterError && err.code === 'LIMIT_UNEXPECTED_FILE') {
        res.status(400).end('Too many files uploaded');
    }
})

app.post('/ccc', upload.fields([
    { name: 'aaa', maxCount: 3 },
    { name: 'bbb', maxCount: 2 }
]), function (req, res, next) {
    console.log('req.files', req.files);
    console.log('req.body', req.body);
})

app.listen(5200);

通过 fields 方法指定每个字段的名字和最大数量,接收到请求后通过 req.files[‘xxx’] 来取对应的文件信息,其他非文件字段,同样是通过 req.body 来取
修改index.html代码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://unpkg.com/axios@0.24.0/dist/axios.min.js"></script>
</head>

<body>
    <input id="fileInput" type="file" multiple />
    <script>
        const fileInput = document.querySelector('#fileInput');

        async function formData2() {
            const data = new FormData();
            data.set('name', '光');
            data.set('age', 20);
            [...fileInput.files].forEach(item => {
                data.append('bbb', item)
            })

            const res = await axios.post('http://localhost:5200/bbb', data);
            console.log(res);
        }

        async function formData3() {
            const data = new FormData();
            data.set('name', '光');
            data.set('age', 20);
            data.append('aaa', fileInput.files[0]);
            data.append('aaa', fileInput.files[1]);
            data.append('bbb', fileInput.files[2]);
            data.append('bbb', fileInput.files[3]);

            const res = await axios.post('http://localhost:5200/ccc', data);
            console.log(res);
        }

        fileInput.onchange = formData3;
    </script>
</body>

</html>

可以看到服务端上传了4个新的文件
1719648315461.png
1719648371187.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1917781.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python学习01-安装

一.安装python 1.下载安装 首先要先下载安装包&#xff1a;Download Python | Python.org 网上建议下载python3.7.4版本&#xff0c;那就下载这个版本 2.验证 二.pip 1.升级pip pip 是 Python 的包管理工具&#xff0c;该工具提供了对Python 包的查找、下载、安装、卸载的…

BigMarket-基础层持久化数据库

需求 工程对接数据库 图例 结构说明 app-主要用于启动&#xff0c;没有业务逻辑 domain-业务逻辑&#xff0c;如积分的兑换&#xff0c;抽奖&#xff0c; infrastructure-基础层&#xff0c;技术支持&#xff0c;数据服务数据持久化&#xff1a;MySQL&#xff0c;redis&am…

在NVIDIA Jetson平台离线部署大模型

在NVIDIA Jetson平台离线部署大模型&#xff0c;开启离线具身智能新纪元。 本项目提供一种将LMDeploy移植到NVIDIA Jetson系列边缘计算卡的方法&#xff0c;并在Jetson计算卡上运行InternLM系列大模型&#xff0c;为离线具身智能提供可能。 最新新闻&#x1f389; [2024/3/1…

2024最适合小白的Midjourney教程,值得收藏!

一、Midjourney 的提示词 1、提示可以包括一个或多个图像 URL、多个文本短语以及一个或多个参数 1&#xff09;Image Prompts&#xff08;图像提示&#xff09;&#xff1a;可以将图像 URL 添加到提示中以影响最终结果的样式和内容。图像 URL 始终出现在提示的前面。文件应以.…

小型内衣裤洗衣机哪个牌子好?五大卓越臻品不容错过!

随着科技的发展&#xff0c;市面上也出现许多便利的小家电。其中被多次讨论起来的莫过于是内衣洗衣机&#xff0c;选择一款耐用、质量优秀的内衣洗衣机&#xff0c;不仅可以减少洗衣负担&#xff0c;还能提供高效的洗涤效果。然而&#xff0c;随着内衣洗衣机的爆火&#xff0c;…

一种低导通损耗的USB 电源开关电路

摘 要&#xff1a;本文设计了一种低导通损耗的USB 电源开关电路。该电路采用自举电荷泵为N 型功率管提供足够高的栅压&#xff0c; 以降低USB 开关的导通损耗。在过载情况下&#xff0c; 过流保护电路能将输出电流限制在0. 3 A。 1 引言 通用串行总线&#xff08; Universal …

windows使用foxglove可视化

1 部署 安装桌面应用 Download - Foxglove 安装完毕后按照要求要注册账号&#xff0c;注册完账号即可正常打开foxglove; 下载ecal-foxglove-bridge.exe&#xff0c;作用是转发ecal话题到foxglove GitHub - eclipse-ecal/ecal-foxglove-bridge: ecal-foxglove-server 2. 可…

人脸表情识别Facial Expression Recognition基于Python3和Keras2(TensorFlow后端)

人脸表情识别项目是一个结合了计算机视觉和深度学习技术的高级应用&#xff0c;主要用于分析和理解人类面部表情所传达的情感状态。这样的系统可以用于多种场景&#xff0c;比如情绪分析、用户交互、市场调研、医疗诊断以及人机接口等领域。 一个典型的人脸表情识别项目可以分…

开源项目的发展趋势之托管平台

引言 回溯至十五年前的求学时光&#xff0c;当我们初涉编程的浩瀚海洋&#xff0c;面对程序设计这一崭新挑战&#xff0c;曾渴望能有一份现成的源码作为启航的灯塔。然而&#xff0c;在那个时代&#xff0c;除了有限的SDK资源外&#xff0c;寻觅到高质量、可借鉴的源代码并非易…

如何给CAD文件加密丨五种超级简单的CAD图纸加密方法

CAD图纸作为企业核心竞争力的体现&#xff0c;其安全性直接关系到企业的生产效率和市场竞争力。一旦图纸被泄露&#xff0c;竞争对手可能会迅速模仿或改进产品&#xff0c;从而抢占市场份额。此外&#xff0c;图纸的非法获取还可能涉及知识产权纠纷&#xff0c;给企业带来法律风…

MES 功能模块

MES系统&#xff08;Manufacturing Execution System&#xff0c;生产执行系统&#xff09;是制造业企业的关键管理系统之一&#xff0c;它通过集成生产计划、工艺流程、物料管理和生产过程数据等&#xff0c;实现了对生产和制造过程的全面管理和监控。MES系统的功能模块主要包…

FPGA-Verilog-Vivado-软件使用

这里写目录标题 1 软件配置2 FPGA-7000使用2.1 运行启动方式 1 软件配置 编辑器绑定为Vscode&#xff0c;粘贴VS code运行文件的目录&#xff0c;后缀参数保持不变&#xff1a; 如&#xff1a; D:/Users/xdwu/AppData/Local/Programs/Microsoft VS Code/Code.exe [file name]…

vscode远程调试python代码

第一步&#xff1a; vscode设置 vscode也支持通过remote的方法连接我们在命令行中发起的debug server。首先我们要配置一下debug的config。 还是点击VSCode侧边栏的“Run and Debug”&#xff08;运行和调试)&#xff0c;单击"create a lauch.json file" 第二步&a…

Java--static详解

1.static静态的意义&#xff0c;加在属性面前就为静态属性&#xff1b;加在方法面前就为静态方法 2.如图&#xff0c;定义了一个静态属性age&#xff0c;一个非静态属性score&#xff1b; 输出语句一共四句&#xff0c;其中第三句报错&#xff0c;由于静态和非静态的区别&…

软考:软件设计师 — 2.操作系统

二. 操作系统 1. 操作系统概念 &#xff08;1&#xff09;操作系统的作用 操作系统是计算机硬件之上的第一层软件系统。 操作系统通常用来&#xff1a; 管理系统的硬件、软件、数据资源。控制程序运行。人机之间的接口。应用软件与硬件之间的接口。 可概括为&#xff1a; …

7.11 cf div3 C

Problem - C - Codeforces 操作 根据给定的索引数组ind和字符串c&#xff0c;按照一定的顺序修改字符串s中对应位置的字符。具体来说&#xff0c;第i次操作会修改s中索引为indi的位置的字符&#xff0c;将其设置为ci。 将c字符串按照从小到大排序&#xff0c;替换ind数组所表…

迅为RK3588S开发板广泛用于边缘技术,人工智能,智能家居,智慧零售,智能网关等

性能强 iTOP-3588S开发板采用瑞芯微RK3588S处理器&#xff0c;是全新一代AloT高端应用芯片&#xff0c;搭载八核64位CPU&#xff0c;四核Cortex-A76和四核Cortex-A55架构主频高达2.4GHZ&#xff0c;8GB内存&#xff0c;32GBEMMC。 四核心架构GPU内置GPU可以完全兼容0penGLES1.1…

vscode c++可以找到声明却无法自动补全

这个问题折磨了我将近一个月&#xff0c;今天终于被解决了&#xff0c;特此记录 情景再现 事情的起因是我在学习华为的Ascend C算子&#xff0c;需要编写C代码。关于怎么下载库文件怎么编译之类的不是本文的重点&#xff0c;重点是自动补全。 我已经拿到库文件了&#xff0c…

动漫3d模型设计需要注意什么?---模大狮模型网

设计动漫3D模型时&#xff0c;有几个方面需要注意&#xff1a; 保持角色风格一致性&#xff1a; 动漫通常有独特的风格和美学&#xff0c;设计时要确保模型与所代表的角色或作品的整体风格相符。注意保持线条和比例的一致性&#xff0c;使模型能够忠实地呈现原作的特点。 注重…

论文降痕降重全攻略:从技巧到工具,助你轻松应对学术挑战

AIGC降重工具&#xff1a;快速降低论文查重率 高查重率是许多毕业生的困扰。通常&#xff0c;高查重率源于过度引用未经修改的参考资料和格式错误。传统的降重方法&#xff0c;如修改文本和增添原创内容&#xff0c;虽必要但耗时且成效不一。 鉴于此&#xff0c;应用AI工具进…