第十九章 Nest multer 文件上传

news2024/7/31 4:24:15

上章我们了解了Express multer 文件上传的相关操作 本章将了解Nest中的文件上传。用 multer 包处理 multipart/form-data 类型的请求中的 file

新建个 nest 项目:

nest new nest-multer-upload 

1719665836394.png
安装 multer 的 ts 类型的包:

npm install -D @types/multer

1719667026173.png

1、单文件上传

接着创建一个接口,用于文件上传 下面的test1接口就是用于文件上传

import { Body, Controller, Get, Post, UploadedFile, UseInterceptors } from '@nestjs/common';
import { AppService } from './app.service';
import { FileInterceptor } from '@nestjs/platform-express';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) { }

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }

  @Post('test1')
  @UseInterceptors(FileInterceptor('file', {
    dest: 'uploads',
  }))
  uploadFile(@UploadedFile() file: Express.Multer.File, @Body() body: any) {
    console.log('body', body);
    console.log('file', file);

  }
}

使用 FileInterceptor 来提取 file 字段,然后通过 UploadedFile 装饰器把它作为参数传入
接着运行项目可以看到我们的项目根目录下创建了一个uploads名称的文件夹
1719668539032.png
在nestjs项目中设置支持跨域
修改main.ts:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule, {
    cors: true
  });
  await app.listen(3000);
}
bootstrap();

接着 我们来编写前端的代码,创建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 formData() {
            const data = new FormData();
            data.set('name', '测试');
            data.set('age', 36);
            data.set('file', fileInput.files[0]);

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

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

</html>

运行前端:

npx http-server

1719717782702.png
浏览器访问:
1719718137459.png
上传文件之后可以看控制台看到打印了上传的file 对象 和body数据,文件也保存到了 uploads 目录下
1719718212331.png

2、多文件上传

增加test2接口 注意哦 FilesInterceptor UploadedFiles 是加了s的 和之前的单文件上传不一样

@Post('test2')
  @UseInterceptors(FilesInterceptor('files', 3, {
    dest: 'uploads',
  }))
  uploadFiles(@UploadedFiles() files: Express.Multer.File[], @Body() body: any) {
    console.log('body', body);
    console.log('files', files);
  }

接着我们在前端代码新增一个函数 formData2:

<!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 formData() {
            const data = new FormData();
            data.set('name', '测试');
            data.set('age', 36);
            data.set('file', fileInput.files[0]);

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

        async function formData2() {
            const data = new FormData();
            data.set('name', '测试');
            data.set('age', 36);
            [...fileInput.files].forEach(item => {
                data.append('file', item);
            })

            const res = await axios.post('http://localhost:3000/test2', data, {
                Headers: { 'content-type': 'multipart/form-data' }
            });

            console.log(res);
        }

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

</html>

重新运行前端:

npx http-server

接着上传多个文件之后 可以看到控制台打印了 files 文件数组
1719719733484.png

3、多字段上传

接下来我们测试一下多字段上传
新增加 test3接口 使用 FileFieldsInterceptor UploadedFiles

import { Body, Controller, Get, Post, UploadedFile, UploadedFiles, UseInterceptors } from '@nestjs/common';
import { AppService } from './app.service';
import { FileFieldsInterceptor, FileInterceptor, FilesInterceptor } from '@nestjs/platform-express';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) { }

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }

  @Post('test1')
  @UseInterceptors(FileInterceptor('file', {
    dest: 'uploads',
  }))
  uploadFile(@UploadedFile() file: Express.Multer.File, @Body() body: any) {
    console.log('body', body);
    console.log('file', file);
  }


  @Post('test2')
  @UseInterceptors(FilesInterceptor('files', 3, {
    dest: 'uploads',
  }))
  uploadFiles(@UploadedFiles() files: Express.Multer.File[], @Body() body: any) {
    console.log('body', body);
    console.log('files', files);
  }

  @Post('test3')
  @UseInterceptors(FileFieldsInterceptor([
    { name: 'a', maxCount: 2 },
    { name: 'b', maxCount: 3 },
  ]))
  uploadFileFields(@UploadedFiles() files: { aaa?: Express.Multer.File[], bbb?: Express.Multer.File[] }, @Body() body) {
    console.log('body', body);
    console.log('files', files);
  }
}

修改前端代码 增加 formData3 实现上传4个文件 前两个文件上传的时候在a字段 后两个文件上传的时候在b字段实现上传:

<!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 formData() {
            const data = new FormData();
            data.set('name', '测试');
            data.set('age', 36);
            data.set('file', fileInput.files[0]);

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

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

            const res = await axios.post('http://localhost:3000/test2', data, {
                Headers: { 'content-type': 'multipart/form-data' }
            });

            console.log(res);
        }

        async function formData3() {
            const data = new FormData();
            data.set('name', '测试');
            data.set('age', 36);
            data.append('a', fileInput.files[0])
            data.append('a', fileInput.files[1])
            data.append('b', fileInput.files[2])
            data.append('b', fileInput.files[3])

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

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

</html>

重新运行前端:

npx http-server

接着打开 http://127.0.0.1:8080/ 上传4个文件
1719723208742.png
可以看到 a 字段收到了2个文件 b字段收到了2个文件

4、任意字段上传

如果我们不知道有哪些字段是上传的 可以使用AnyFilesInterceptor,新建接口test4:

@Post('test4')
  @UseInterceptors(AnyFilesInterceptor({
    dest: 'uploads',
  }))
  uploadAnyFiles(@UploadedFiles() files: Array<Express.Multer.File>, @Body() body) {
    console.log('body', body);
    console.log('files', files);
  }

修改前端代码 增加 formData4 函数:

<!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 formData() {
            const data = new FormData();
            data.set('name', '测试');
            data.set('age', 36);
            data.set('file', fileInput.files[0]);

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

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

            const res = await axios.post('http://localhost:3000/test2', data, {
                Headers: { 'content-type': 'multipart/form-data' }
            });

            console.log(res);
        }

        async function formData3() {
            const data = new FormData();
            data.set('name', '测试');
            data.set('age', 36);
            data.append('a', fileInput.files[0])
            data.append('a', fileInput.files[1])
            data.append('b', fileInput.files[2])
            data.append('b', fileInput.files[3])

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

        async function formData4() {
            const data = new FormData();
            data.set('name', '测试');
            data.set('age', 36);
            data.set('aaa', fileInput.files[0]);
            data.set('bbb', fileInput.files[1]);
            data.set('ccc', fileInput.files[2]);
            data.set('ddd', fileInput.files[3]);

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

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

</html>

重新运行前端:

npx http-server

接着打开 http://127.0.0.1:8080/ 上传4个文件 可以看到识别了所有字段
1719724483848.png
同时也可以指定storage,转换上传的文件名称 创建 storage.ts

import * as multer from "multer";
import * as fs from 'fs';
import * as path from "path";

const storage = multer.diskStorage({
    destination: function (req, file, cb) {
        try {
            fs.mkdirSync(path.join(process.cwd(), 'my-uploads'));
        }catch(e) {}

        cb(null, path.join(process.cwd(), 'my-uploads'))
    },
    filename: function (req, file, cb) {
        const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9) + '-' + file.originalname
        cb(null, file.fieldname + '-' + uniqueSuffix)
    }
});

export { storage };

修改之前的test4接口:

import { Body, Controller, Get, Post, UploadedFile, UploadedFiles, UseInterceptors } from '@nestjs/common';
import { AppService } from './app.service';
import { AnyFilesInterceptor, FileFieldsInterceptor, FileInterceptor, FilesInterceptor } from '@nestjs/platform-express';
import { storage } from './storage ';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) { }

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }

  @Post('test1')
  @UseInterceptors(FileInterceptor('file', {
    dest: 'uploads',
  }))
  uploadFile(@UploadedFile() file: Express.Multer.File, @Body() body: any) {
    console.log('body', body);
    console.log('file', file);
  }


  @Post('test2')
  @UseInterceptors(FilesInterceptor('files', 3, {
    dest: 'uploads',
  }))
  uploadFiles(@UploadedFiles() files: Express.Multer.File[], @Body() body: any) {
    console.log('body', body);
    console.log('files', files);
  }

  @Post('test3')
  @UseInterceptors(FileFieldsInterceptor([
    { name: 'a', maxCount: 2 },
    { name: 'b', maxCount: 3 },
  ]))
  uploadFileFields(@UploadedFiles() files: { aaa?: Express.Multer.File[], bbb?: Express.Multer.File[] }, @Body() body) {
    console.log('body', body);
    console.log('files', files);
  }

  @Post('test4')
  @UseInterceptors(AnyFilesInterceptor({
    dest: 'uploads',
    storage: storage
  }))
  uploadAnyFiles(@UploadedFiles() files: Array<Express.Multer.File>, @Body() body) {
    console.log('body', body);
    console.log('files', files);
  }


}

再次打开游览器 http://127.0.0.1:8080/ 上传4个文件
1719730782749.png

5、文件上传限制

接下来我们对上传的文件进行显示 文件大小、类型等,这部分我们在pipe里实现

nest g pipe file-size-validation-pipe --no-spec --flat

1719730968608.png
修改ize-validation-pipe.pipe.ts 设置文件要小于20kb

import { PipeTransform, Injectable, ArgumentMetadata, HttpException, HttpStatus } from '@nestjs/common';

@Injectable()
export class FileSizeValidationPipe implements PipeTransform {
  transform(value: Express.Multer.File, metadata: ArgumentMetadata) {
    if(value.size > 20 * 1024) {
      throw new HttpException('文件大于 20k', HttpStatus.BAD_REQUEST);
    }
    return value;
  }
}

添加到接口里 FileSizeValidationPipe:

@Post('test1')
  @UseInterceptors(FileInterceptor('file', {
    dest: 'uploads',
  }))
  uploadFile(@UploadedFile(FileSizeValidationPipe) file: Express.Multer.File, @Body() body: any) {
    console.log('body', body);
    console.log('file', file);
  }

接着把前端代码修改一下

<!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 formData() {
            const data = new FormData();
            data.set('name', '测试');
            data.set('age', 36);
            data.set('file', fileInput.files[0]);

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

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

            const res = await axios.post('http://localhost:3000/test2', data, {
                Headers: { 'content-type': 'multipart/form-data' }
            });

            console.log(res);
        }

        async function formData3() {
            const data = new FormData();
            data.set('name', '测试');
            data.set('age', 36);
            data.append('a', fileInput.files[0])
            data.append('a', fileInput.files[1])
            data.append('b', fileInput.files[2])
            data.append('b', fileInput.files[3])

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

        async function formData4() {
            const data = new FormData();
            data.set('name', '测试');
            data.set('age', 36);
            data.set('aaa', fileInput.files[0]);
            data.set('bbb', fileInput.files[1]);
            data.set('ccc', fileInput.files[2]);
            data.set('ddd', fileInput.files[3]);

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

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

</html>

重新运行前端: 上传文件一张大于20kb的图片或文件

npx http-server

可以发现接口报错 这样就可以实现文件的校验
1719731591999.png
其实 Nest 内置了文件大小、类型的校验 接下来我们测试一下:
修改test1接口 使用Nest 内置的 ParseFilePipe,它的作用是调用传入的 validator 来对文件做校验。
比如 MaxFileSizeValidator 是校验文件大小、FileTypeValidator 是校验文件类型。

@Post('test1')
  @UseInterceptors(FileInterceptor('file', {
    dest: 'uploads',
  }))
  uploadFile(@UploadedFile(new ParseFilePipe({
    validators: [
      new MaxFileSizeValidator({ maxSize: 1000 }),
      new FileTypeValidator({ fileType: 'image/jpeg' })
    ]
  })) file: Express.Multer.File, @Body() body: any) {
    console.log('body', body);
    console.log('file', file);
  }

接下来我们再上传文件测试一下 可以看到返回了400和具体错误信息
1719731967044.png
接下来我们自定义一下返回的错误信息: 使用 exceptionFactory 自定义错误信息

@Post('test1')
  @UseInterceptors(FileInterceptor('file', {
    dest: 'uploads',
  }))
  uploadFile(@UploadedFile(new ParseFilePipe({
    validators: [
      new MaxFileSizeValidator({ maxSize: 1000 }),
      new FileTypeValidator({ fileType: 'image/jpeg' })
    ],
    exceptionFactory(error) {
      throw new HttpException('测试' + error, 400);
    },
  })) file: Express.Multer.File, @Body() body: any) {
    console.log('body', body);
    console.log('file', file);
  }

再次上传可以看到返回了自定义的错误信息
1719732165228.png
我们也可以自己实现Validator
创建 my-file-validator.ts

import { FileValidator } from "@nestjs/common";

export class MyFileValidator extends FileValidator{
    constructor(options) {
        super(options);
    }

    isValid(file: Express.Multer.File): boolean | Promise<boolean> {
        if(file.size > 10000) {
            return false;
        }
        return true;
    }
    buildErrorMessage(file: Express.Multer.File): string {
        return `文件 ${file.originalname} 大小超出 10k`;
    }
}

修改接口使用自定义的validator:

@Post('test1')
  @UseInterceptors(FileInterceptor('file', {
    dest: 'uploads',
  }))
  uploadFile(@UploadedFile(new ParseFilePipe({
    validators: [
      new MyFileValidator({}),
    ],
    exceptionFactory(error) {
      throw new HttpException('测试' + error, 400);
    },
  })) file: Express.Multer.File, @Body() body: any) {
    console.log('body', body);
    console.log('file', file);
  }

上传文件:
1719732568683.png

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

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

相关文章

Cesium中实现图层组

图层组 某天领导找我&#xff0c;说业务中可能存在多个影像服务为一个图层组&#xff0c;并且需要同时加载和同时在图层列表中上下移动的需求。 例如一些专题地图&#xff0c;包含所有学校、医院、公交站等图层&#xff0c;而这些图层都是单独发布的。 在 Cesium 中确实存在…

响应式建站公司企业官网源码系统 带源代码以及搭建部署教程

系统概述 响应式建站公司企业官网源码系统是一套集设计、开发、部署于一体的综合性解决方案。它旨在为企业提供一个易于定制、功能强大、适应各种设备屏幕的官方网站平台。 该系统采用先进的技术架构&#xff0c;确保网站的稳定性和性能。它能够与各种后端数据库和服务器环境…

爱秀国际英语公信力怎么样?靠谱吗?

同爱秀国际英语公信力怎么样&#xff1f; ①爱秀国际英语成立于09年&#xff0c;已经有15年的教学积累&#xff0c;专门针对大学生研发的英语口语课程。 ②历年来不仅教学效果显著&#xff0c;在社会上也获得过很多荣誉&#xff0c;在历年的教育大会上也荣获过诸多认可&…

一招杜绝 | 网站被劫持强制植入广告的问题

在我们日常上网过程中&#xff0c;经常会遇到打开一个网页&#xff0c;网页都还没有显示出来&#xff0c;一堆广告就弹出来的现象。或者网页刚刚打开&#xff0c;没几分钟 就会弹出来某游戏广告&#xff0c;注册领豪华坐骑等等的小广告。这些广告不仅仅会让我们对网站的真实性产…

eplan软件许可优化解决方案

Eplan软件介绍 Eplan是一款专业的电气设计软件&#xff0c;用于自动化工程和电气系统的设计与文档化。它由德国的Eplan Software & Service GmbH开发&#xff0c;并在全球范围内广泛应用于工程设计和电气工程领域。 Eplan软件提供了全面的工具和功能&#xff0c;以简化和优…

202-509SF 同轴连接器

型号简介 202-509SF是Southwest Microwave的连接器。这款连接器机身和法兰由不锈钢合金 UNS-30300 制成&#xff0c;螺纹接头则采用 5C360 黄铜合金。接触点采用 BeCu 合金&#xff0c;并经过镀金处理&#xff0c;以提供优异的导电性和耐腐蚀性。绝缘体则由 PTFE 氟碳或 ULTEM …

3.动态规划.基础

3.动态规划.基础 基础理论背包基础理论01背包完全背包多重背包 题目1.斐波那契数2.爬楼梯3.使用最小花费爬楼梯4.不同路径5.不同路径2 基础理论 动态规划&#xff0c;英文&#xff1a;Dynamic Programming&#xff0c;简称DP&#xff0c;如果某一问题有很多重叠子问题&#xf…

外卖霸王餐系统有什么推荐的

​ 在当今数字化的商业环境中&#xff0c;各种创新的营销策略层出不穷&#xff0c;其中微客云霸王餐系统以其独特的商业模式和营销策略&#xff0c;受到了众多商家的青睐。该系统不仅为商家提供了一个高效的营销工具&#xff0c;还通过一系列的功能和优势&#xff0c;帮助商家…

Qt QChart 曲线图表操作

学习目标&#xff1a;QChart 曲线图表操作 学习内容 QT中的QChart类提供了一个功能强大的图表绘制框架,可以根据需求方便高效地绘制各种类型的图表,主要特点如下: 支持多种常见图表类型,如线图、条形图、饼图、散点图等各种类型。开发者只需要选择合适的图表类和数据即可绘制…

Android APT实战

Android开发中,注解平时我们用的比较多,也许我们会比较好奇,注解的背后是如何工作的,这篇文章帮大家一步步创建一个简单的注解处理器。 简介 APT(Annotation Processing Tool)即注解处理器,在编译的时候可以处理注解然后搞一些事情,也可以在编译时生成一些文件之类的。…

【Linux】常见指令收官权限理解

tar指令 上一篇博客已经介绍了zip/unzip指令&#xff0c;接下来我们来看一下另一个关于压缩和解压的指令&#xff1a;tar指令tar指令&#xff1a;打包/解包&#xff0c;不打开它&#xff0c;直接看内容 关于tar的指令有太多了&#xff1a; tar [-cxtzjvf] 文件与目录 ...…

2.4G芯片开发的遥控玩具方案介绍 东莞酷得

玩具从早期的简单功能&#xff0c;到现如今各种各样的智能操作&#xff0c;发展的速度也是飞速的。随着玩具市场的逐步完善与推进&#xff0c;中国的智能玩具市场也出现了很多远程遥控玩具。遥控玩具也是从最初的有线到现在的无线&#xff0c;从地上跑的到天上飞的&#xff0c;…

jmeter分布式(四)

一、gui jmeter的gui主要用来调试脚本 1、先gui创建脚本 先做一个脚本 演示&#xff1a;如何做混合场景的脚本&#xff1f; 用211的业务比例 ①启动数据库服务 数据库服务&#xff1a;包括mysql、redis mysql端口默认3306 netstat -lntp | grep 3306处于监听状态&#xf…

LeetCode 88.合并两个有序数组 C写法

LeetCode 88.合并两个有序数组 C写法 思路&#xff1a; ​ 由题nums1的长度为mn&#xff0c;则我们不需要开辟新的数组去存储元素。题目要求要有序合并&#xff0c;于是可以判断哪边数更大&#xff0c;将更大的数尾插在nums1中。 ​ 定义三个变量来控制下标&#xff0c;end1控…

Linux--线程ID封装管理原生线程

目录 1.线程的tid&#xff08;本质是线程属性集合的起始虚拟地址&#xff09; 1.1pthread库中线程的tid是什么&#xff1f; 1.2理解库 1.3phtread库中做了什么&#xff1f; 1.4线程的tid&#xff0c;和内核中的lwp 1.5线程的局部存储 2.封装管理原生线程库 1.线程的tid…

四川赤橙宏海商务信息咨询有限公司抖音电商服务靠谱吗?

在数字化浪潮席卷全球的今天&#xff0c;电商行业蓬勃发展&#xff0c;各种新兴电商平台层出不穷。其中&#xff0c;抖音电商以其独特的社交属性和庞大的用户基础&#xff0c;迅速崛起为行业新星。四川赤橙宏海商务信息咨询有限公司&#xff0c;作为专注于抖音电商服务的佼佼者…

自动编码器(Autoencoders)

在“深度学习”系列中&#xff0c;我们不会看到如何使用深度学习来解决端到端的复杂问题&#xff0c;就像我们在《A.I. Odyssey》中所做的那样。我们更愿意看看不同的技术&#xff0c;以及一些示例和应用程序。 1、引言 ① 什么是自动编码器&#xff08;AutoEncoder&#xff…

【js/ts】js/ts高精度加减乘除函数

加法 /*** 高精度加法函数&#xff0c;处理字符串或数字输入&#xff0c;去除尾部多余的零* param {string|number} a - 被加数* param {string|number} b - 加数* returns {string} - 计算结果&#xff0c;去除尾部多余的零* throws {Error} - 如果输入不是有效的数字&#x…

油罐车的罐体结构介绍

油罐车的罐体一般用优质低碳钢板制成&#xff0c;罐内被隔板分为前、后两部分&#xff0c;相互隔离。每个舱内部均配备一道防波板&#xff0c;以加强罐体的稳定性并减缓行驶中油料对罐体的冲击。其车身由车架、车厢等组成&#xff0c;车架是整个油罐车的骨架&#xff0c;承载着…

项目收获总结--本地缓存方案选型及使用缓存的坑

本地缓存方案选型及使用缓存的坑 一、摘要二、本地缓存三、本地缓存实现方案3.1 自己编程实现一个缓存3.2 基于 Guava Cache 实现本地缓存3.3 基于 Caffeine 实现本地缓存3.4 基于 Encache 实现本地缓存3.5 小结 四、使用缓存的坑4.1 缓存穿透4.2 缓存击穿4.3 缓存雪崩4.4 数据…