上传文件

安装依赖

1
2
3
npm install @nestjs/platform-express  # Nestjs自带的
npm install multer@1.4.5-lts.1 -S # 默认安装2.0.0,引入包就报错,所以要指定成旧版本
npm install @types/multer -D

资源存放路径

在module中注册:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import { Module } from '@nestjs/common';
import { UploadService } from './upload.service';
import { UploadController } from './upload.controller';
import { MulterModule } from '@nestjs/platform-express';
import { diskStorage } from 'multer';
import { extname, join } from 'path';

@Module({
imports: [
MulterModule.register({
// 指定上传文件后存放的路径,用diskStorage指定路径
storage: diskStorage({
// 指定存放位置
destination: join(__dirname, '../images'),
// 重命名
filename: (_, file, callback) => {
// extname可以截取文件内容(比如获得后缀名)
const fileName = `${
new Date().getTime() + extname(file.originalname)
}`;
return callback(null, fileName);
},
}),
}),
],
controllers: [UploadController],
providers: [UploadService],
})
export class UploadModule {}

文件上传接口

在controller中编写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import {
Controller,
Post,
UseInterceptors,
UploadedFile,
} from '@nestjs/common';
import { UploadService } from './upload.service';
import { CreateUploadDto } from './dto/create-upload.dto';
import { UpdateUploadDto } from './dto/update-upload.dto';
// 上传单个文件的中间件、上传多个文件的中间件
import { FileInterceptor, FilesInterceptor } from '@nestjs/platform-express';

@Controller('upload')
export class UploadController {
constructor(private readonly uploadService: UploadService) {}

// 上传文件
@Post('album')
// 指定处理中间件,使用上传单个文件的中间件
@UseInterceptors(FileInterceptor('file'))
// 使用@UploadedFile接收file
upload(@UploadedFile() file) {
console.log(file, 'file');
return 'omg';
}
}

静态资源目录

在main.ts中指定:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { NestFactory } from '@nestjs/core';
import { VersioningType } from '@nestjs/common';
import { AppModule } from './app.module';
import { NestExpressApplication } from '@nestjs/platform-express';
import { join } from 'path';

async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule);
app.enableVersioning({
type: VersioningType.URI,
});
// 配置静态资源目录
app.useStaticAssets(join(__dirname, 'images'), {
// 配置自定义路径前缀
prefix: '/images',
});
await app.listen(3000);
}
bootstrap();

下载文件

Download下载

在controller中编写:

1
2
3
4
5
6
// download下载方式
@Get('export')
download(@Res() res: Response) {
const url = join(__dirname, '../images/1690969695525.png');
res.download(url);
}

文件流下载

后端提供文件流

安装压缩文件的依赖:

1
npm install compressing -s

在controller中编写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 流下载方式
@Get('stream')
async down(@Res() res: Response) {
const url = join(__dirname, '../images/1690969695525.png');
// 压缩文件
const tarStream = new zip.Stream();
await tarStream.addEntry(url);

const filename = url.substring(url.lastIndexOf('\\') + 1);

// 设置请求头
res.setHeader('Content-Type', 'application/octet-stream');
res.setHeader('Content-Disposition', `attachment; filename=${filename}`);

// 变成二进制流文件
tarStream.pipe(res);
}

前端接收文件流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<template>
<button @click="download">
下载
</button>
</template>

<script setup lang="ts">
const download = ()=> {
// 这样也可以
// window.open('http://localhost:3000/upload/stream')
// 但是这样更安全
useFetch('http://localhost:3000/upload/stream')
}

// 前端接收流文件
// axios也一样,需要使用ArrayBuffer和Blob
const useFetch = async (url: string)=> {
const res = await fetch(url).then(res=> res.arrayBuffer())
console.log(res,'res')
const blob = new Blob([res])
console.log(blob,'blob')
const urll = URL.createObjectURL(blob)
console.log(urll,'urll')
const a = document.createElement('a')
a.href = urll
a.download = 'omg.zip'
a.click()
}
</script>