上传资源

multer一个基于 Express中间件用于处理 multipart/form-data 格式数据,主要用于上传文件
NestJS 内置multer,可以使用 @nestjs/platformexpress 包中导出FileInterceptorFilesInterceptor拦截器使用 multer 的功能

  1. npm i multernpm i @types/multer -D
  2. nest g res user --no-spec
  3. 配置 module 文件
import { Module } from '@nestjs/common';
import { UserController } from './user.controller';
import { MulterModule } from '@nestjs/platform-express';
import { diskStorage } from 'multer';
import { extname, join } from 'path';

// 配置文件上传
const multerOptions: MulterOptions = {
    // 配置文件存储
    storage: diskStorage({
        // 存储地址
        destination: join(__dirname, '../../../public/notification-attachment'),
        // 存储名称
        filename: (_req, file, callback) => {
            const suffix = extname(file.originalname); // 获取文件后缀
            const docName = new Date().getTime(); // 自定义文件名
            return callback(null, `${docName}${suffix}`);
        },
    }),
    // 过滤存储文件
    fileFilter: (_req, file, callback) => {
        // multer 默认使用 latin1 编码解析文件名, 而 latin1 编码支持中文字符, 所以会出现中文乱码的现象
        // 这里将文件名从 latin1 编码转换为 Buffer 对象, 再用 toString('utf8') 将 Buffer 对象转换为 utf8 编码字符串
        // utf8 是一种支持多国语言编码方式, 这样就可以保证文件名的中文字符不会被错误解析
        file.originalname = Buffer.from(file.originalname, 'latin1').toString(
            'utf8',
        );
        callback(null, true);
    },
    // 限制文件大小
    limits: {
        // 限制文件大小为 10 MB
        fileSize: 10 * 1024 * 1024, // 默认限制
        // 限制文件名长度为 50 bytes
        fieldNameSize: 50, // 默认 100 bytes
    },
};

@Module({
    imports: [
        MulterModule.register(multerOptions),
        // 如需异步配置, 可使用 MulterModule.registerAsync
    ],
    controllers: [UserController],
})
export class UserModule {}
  1. 配置 controller 文件

上传单个文件时,使用拦截器 FileInterceptor('参数名')FileInterceptor 会将上传的文件注入控制器方法参数中,你可以@UploadedFile() 装饰器来获取

import {
    Controller,
    Post,
    UseInterceptors,
    UploadedFile,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express/multer';

@Controller('user')
export class UserController {
    @Post('album')
    @UseInterceptors(FileInterceptor('picture')) // 使用拦截器 FileInterceptor
    upload(@UploadedFile() file: Express.Multer.File /* 获取上传的文件 */ ) {
        return { file };
    }
}
  1. 使用 Apifox 模拟前端上传图片

前端 POST 请求携带的参数名要与后端拦截器 FileInterceptor('参数名') 中的 '参数名' 一样

image.png

  1. dist 目录下就可以预览前端上传的文件啦

访问已上传的资源

import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express/interfaces';
import { join } from 'path';
import { AppModule } from './app.module';

async function bootstrap() {
    // 显示配置 NestExpressApplication 类型, 以获取更好语法提示
    const app = await NestFactory.create<NestExpressApplication>(AppModule);

    app.useStaticAssets(join(__dirname, './images')); // 配置静态资源目录

    await app.listen(3000);
}
bootstrap();

dist 目录复制上传的图片文件名 XXX打开 http://127.0.0.1:3000/XXX 即可访问上传的图片

image.png

app.useStaticAssets(join(__dirname, './images'), {
    prefix: '/static', // 配置静态资源虚拟路径
});

现在需要打开 http://127.0.0.1:3000/static/XXX 才能访问上传的图片

下载资源

直接下载

使用 Express 的方法 res.download(path[, filename])
path一个字符串表示文件的绝对或相对路径
filename一个可选的字符串,表示建议的文件名,如果省略,则使用 path基本名称

  1. 配置 controller 文件
import { Controller, Get, Res } from '@nestjs/common';
import { Response } from 'express';
import { join } from 'path';

@Controller('user')
export class UserController {
    @Get('album')
    getImg(@Res() res: Response) {
        const url = join(__dirname, '../images/1676791106510.png'); // 正常开发url 应该是从数据库中的
        res.download(url); // 将指定路径的文件作为附件传输浏览器
    }
}

现在访问 http://127.0.0.1:3000/user/album 即可下载图片文件

  1. 配置前端下载
<template>
    <el-button @click="download('/upload/export')">下载图片资源</el-button>
</template>

<script lang="ts" setup>
const download = (url: string) => {
    window.open(url);
};
</script>

文件流下载

compressing 用于压缩和解压缩文件和流,支持 gzipdeflate、ziptartgztbz2 等格式

  1. npm i compressing
  2. 配置 controller 文件
import { Controller, Get, Res } from '@nestjs/common';
import { zip } from 'compressing';
import { Response } from 'express';
import { join } from 'path';

@Controller('user')
export class UserController {
    @Get('photo')
    getImg(@Res() res: Response) {
        const url = join(__dirname, '../images/1676791106510.png'); // 正常开发url 应该是从数据库中的

        const targetStream = new zip.Stream(); // 创建一个可读的压缩流, 可以将任何数据压缩zip 格式
        targetStream.addEntry(url); // 向压缩流中添加文件

        res.setHeader('Content-Type', 'application/octet-stream'); // 设置文件格式为 '流'
        res.setHeader(
            'Content-Disposition', // 设置文件以什么方式呈现
            'attachment; filename=superman',
            // attachment 表示文件应该被下载到本地;    filename=superman 表示下载文件的文件名
        );

        targetStream.pipe(res); // 将压缩流输出响应
    }
}

现在访问 http://127.0.0.1:3000/user/photo 即可下载 “流” 文件

  1. 前端解析并下载 “流” 文件
<template>
    <el-button @click="downloadByStream('/upload/stream')">下载流文件</el-button>
</template>

<script lang="ts" setup>
const downloadByStream = async (url: string) => {
    const res = await fetch(url).then(res => res.arrayBuffer());
    // 注意: 前端接收的是流文件, 这里需要返回 res.arrayBuffer() 而不是 res.json()
    // 如果是使用 axios, 则需要设置 responseType 为 ArrayBuffer / Blob

    const blob = new Blob([res]); // 将流文件转成 blob 形式
    const imgUrl = URL.createObjectURL(blob); // 通过 blob 生成可访问的链接

    const a = document.createElement('a');
    a.href = imgUrl;
    a.download = 'superman.zip';
    a.click();
};
</script>

原文地址:https://blog.csdn.net/Superman_H/article/details/130171512

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_19333.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注