静态目录
上传图片
除了使用自带的@nestjs/platform-express
外,还需要安装multer
与他的类型声明文件
npm i multer
npm i @types/multer -D
生成一个upload模块
nest g res upload
在upload.Module
使用MulterModule.register
注册存放图片的目录,属性storage
需要用到multer
的diskStorage
,通过destination设置存放目录,filename给文件重新命名
upload.module.ts
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({
storage: diskStorage({
destination: join(__dirname, '../images'),
filename: (_, file, callback) => {
const fileName = `${
new Date().getTime() + extname(file.originalname)
}`;
return callback(null, fileName);
},
}),
}),
],
controllers: [UploadController],
providers: [UploadService],
})
export class UploadModule {}
在controller中使用@UploadedFile
装饰器接收file 文件,下面是抽离的代码
upload.controller.ts
import { Controller, Get, Post, Body, Patch, Param, Delete,UseInterceptors,UploadedFile } from '@nestjs/common';
import { UploadService } from './upload.service';
import {FileInterceptor} from '@nestjs/platform-express';//FilesInterceptor表示支持多文件上传
@Controller('upload')
export class UploadController {
constructor(private readonly uploadService: UploadService) {}
@Post('album')
@UseInterceptors(FileInterceptor('file'))
upload (@UploadedFile() file) {
return { filename: file.filename };
}
}
访问图片
我们使用useStaticAssets配置静态资源的访问目录,使用prefix设置访问路径前缀
main.ts
import { NestFactory } from '@nestjs/core';
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.useStaticAssets(join(__dirname,'images'),{
prefix:"/zhangsan"
})
await app.listen(3000);
}
bootstrap();
浏览器输入地址访问
下载图片
download 直接下载
upload.controller.ts
@Get('export/:id')
export(@Param('id') id: string, @Res() res: Response) {
const url = join(__dirname, '../images/' + id + '.png');
res.download(url);
}
在浏览器输入http://localhost:3000/upload/export/1668847935319
就可以下载
使用文件流的方式下载
可以使用compressing把他压缩成一个zip包,也可以不压缩
npm i compressing
核心如下:
upload.controller.ts
import { zip } from 'compressing';
@Get('stream/:id')
async down(@Param('id') id: string, @Res() res: Response) {
const url = join(__dirname, '../images/' + id + '.png');
const tarStream = new zip.Stream();
await tarStream.addEntry(url);
res.setHeader('Content-Type', 'application/octet-stream');
res.setHeader('Content-Disposition', `attachment;filename=${id}.zip`);
tarStream.pipe(res);
}
这种流文件不能直接交给浏览器,需要前端做处理,这里提供两种下载方式
import { Button } from 'antd'
const id = '1668847935319'
function Download() {
const download = async () => {
let fileName = '未命名'
const ret = await fetch('/api/upload/stream/' + id).then(res => {
const fileNameEncode = res.headers.get('content-disposition')?.split('filename=')[1]
if (fileNameEncode) {
fileName = decodeURIComponent(fileNameEncode);// 解码
}
return res.arrayBuffer()
})
const link = document.createElement('a')
link.href = URL.createObjectURL(new Blob([ret]))
link.download = fileName
link.click()
}
const open = () => {
window.open('http://localhost:3000/upload/export/'+id)
}
return (<>
<Button onClick={download}>流的方式下载</Button>
<Button onClick={open}>直接下载</Button>
</>
)
}
export default Download