NestJS学习:图片上传、下载

news2025/7/16 0:37:33

参考

大神的这两篇文章讲的很详细,这里自己也来试一下
小满nestjs(第十三章 nestjs 上传图片-静态目录)

小满nestjs(第十四章 nestjs 下载图片)

上传图片

安装包
需要:multer 和 @nestjs/platform-express,后者nestJs自带了

npm i multer
npm i  @types/multer

创建文件上传模块

nest g res upload

在这里插入图片描述
在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 { join, extname } from 'path';

@Module({
  //里面有register 和 registerAsync 两个方法,前者是同步的,后者是异步的
  imports: [MulterModule.register({
    //图片上传完要存放的位置
    storage: diskStorage({
      destination: join(__dirname, '../images'),//存放的文件路径
      filename: (req, file, callback) => {
        //重新定义文件名,file.originalname 文件的原始名称
        // extname 获取文件后缀
        const fileName = `${new Date().getTime() + extname(file.originalname)}`;
        //返回新的名称,参数1是错误,这里用null就好
        return callback(null, fileName)
      }
    }),
  }
  )],
  controllers: [UploadController],
  providers: [UploadService]
})
export class UploadModule { }

重新启动一下项目,可以看到在dist目录下生成了images目录
在这里插入图片描述
使用
修改upload.controller.ts文件

import { Controller, Post,UseInterceptors,UploadedFile } from '@nestjs/common';
import { UploadService } from './upload.service';
// FileInterceptor用于单文件上传,FilesInterceptor用于多文件上传
import {FileInterceptor,FilesInterceptor} from '@nestjs/platform-express'

@Controller('upload')
export class UploadController {
  constructor(private readonly uploadService: UploadService) {}
  @Post('album')
  // UseInterceptors 处理文件的中间件,file是一个标识名
  @UseInterceptors(FileInterceptor('file'))
  // UploadedFile装饰器是用于读取文件的
  upload (@UploadedFile() file) {
    console.log("file:",file)
    return true
  }
}

大佬用的测试工具是:Apifox,可以自行下载。下载完进行如下配置
在这里插入图片描述
参数名必须与:@UseInterceptors(FileInterceptor('file')) 对应
在这里插入图片描述
可以看到返回值与我们在代码里写的返回值是一致的,同时在项目里也可以找到该文件
在这里插入图片描述

配置静态文件的访问

虽然图片已经上传成功了,但是现在还是无法直接访问,还需要配置静态文件的访问

修改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(AppModule); // 最初的代码
  const app= await NestFactory.create<NestExpressApplication>(AppModule)
  //配置静态文件访问目录
  app.useStaticAssets(join(__dirname,'images'),{
    prefix:"/files/"
  })
  app.useStaticAssets(join(__dirname,'..','public'),{
    // 配置虚拟路径
    prefix:"/files/"
  })
  await app.listen(3000);
}
bootstrap();

注意: 这里有个坑,大佬没有讲到(当然大佬可能觉得不用讲,但是我这样的小白就遇到了)。如果路径配置的有问题,是无法访问到图片的。

app.useStaticAssets(join(__dirname,'images'),{
    prefix:"/files/"
  })

上面这个是访问根目录下的images文件夹下的图片,这里的根目录是dist目录,是打包后的目录
在这里插入图片描述
在这里插入图片描述

app.useStaticAssets(join(__dirname,'..','public'),{
   // 配置虚拟路径
   prefix:"/files/"
 })

还是以dist目录为根目录,..是上一层目录,所以找的文件夹是
在这里插入图片描述
在这里插入图片描述

下载图片

download 直接下载

import { Controller, Post, UseInterceptors, UploadedFile, Get, Res } from '@nestjs/common';
import { UploadService } from './upload.service';
// FileInterceptor用于单文件上传,FilesInterceptor用于多文件上传
import { FileInterceptor, FilesInterceptor } from '@nestjs/platform-express'
import type { Response } from 'express'
import {join} from 'path'

@Controller('upload')
export class UploadController {
  constructor(private readonly uploadService: UploadService) { }
  @Post('album')
  // UseInterceptors 处理文件的中间件,file是一个标识名
  @UseInterceptors(FileInterceptor('file'))
  // UploadedFile装饰器是用于读取文件的
  upload(@UploadedFile() file) {
    console.log("file:", file)
    return true
  }

  // 文件下载
  @Get('export')
  download(@Res() res: Response) {
    //正常应该是从数据库里获取地址
    const url=join(__dirname,'../images/1675781518442.jpg')
    res.download(url)
  }
}

在这里插入图片描述

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

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

相关文章

深入理解Java的Lambda原理

1、前言 Lambda函数的概念其实有很久远的历史了&#xff0c;在Lisa&#xff0c;C#中早有实现。且近年来&#xff0c;开发者对语言的表现力有了更高的要求&#xff0c;Java也在JDK 1.8 中引入了Lambda函数这一概念。虽然截止到写下这段文字的一刻已经过去七年之久&#xff0c;但…

Mybatis框架详解(全)

目录 MyBatis简介 MyBatis整体架构及运行流程 1.数据源配置文件 2.Sql映射文件 3.会话工厂与会话 4.运行流程 mybatis实现增删改查 Mybatis的获取参数的方式 mapper中自定义映射 mybatis注解开发 mybatis缓存 mybatis分页插件 MyBatis简介 MyBatis 是一款优秀的持久…

程序员如何向架构师转型?看完就明白该怎么做了

软件行业技术开发从业人员众多&#xff0c;但具备若干年开发经验的普通的开发人员往往面临个人发展的瓶颈&#xff0c;即如何从普通开发人员转型成高层次的系统架构师和技术管理人员。想成为一名架构师&#xff0c;应当具备全面的知识体系&#xff0c;需要进行系统的学习和实践…

数组(一)-- LeetCode[26][80] 删除有序数组中的重复元素

1 删除有序数组中的重复项 1.1 题目描述 给你一个 升序排列 的数组 nums &#xff0c;请你 原地 删除重复出现的元素&#xff0c;使每个元素 只出现一次&#xff0c;返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。 由于在某些语言中不能改变数组的长度&#xff0c…

FreeRTOS与UCOSIII任务状态对比

FreeRTOS任务状态 1、运行态 正在运行的任务&#xff0c;正在使用处理器的任务。 单核处理器中任何时候都有且只有一个任务处于运行态。 2、就绪态 已经准备就绪&#xff08;非阻塞或挂起&#xff09;&#xff0c;可以立即运行但还没有运行的任务。 正在等待比自己高优先级…

Kafka——消息队列学习总结

定义 Kafka是一个分布式的基于发布/订阅模式的消息队列&#xff08;MQ)&#xff0c;主要应用于大数据实时处理领域。 模式 点对点模式 一对一&#xff0c;消费者主动拉取数据&#xff0c;消费收到后消息清除。 发布/订阅模式 一对多&#xff0c;消费者消费数据后不会清除消息…

JavaScript:使用for in不是一个很好的抉择

for in 如果让你遍历对象中的key和value&#xff0c;你第一个想到的一定是使用for in const o{name:"chengqige",age:23 } for (let key in o){console.log(key,o[key]); }看起来是没有问题的&#xff0c;但是如果我在下面加一行代码&#xff0c;输出的结果就可能让…

JUC并发编程——进程与线程

目录一、进程和线程的概念1.1 进程1.2 线程1.3 进程与线程对比二、并行和并发的概念三、线程基本应用3.1 多线程应用——异步调用一、进程和线程的概念 1.1 进程 ● 程序由指令和数据组成&#xff0c;但这些指令要运行&#xff0c;数据要读写&#xff0c;就必须将指令加载至 …

内容生态与新业务双突破,汽车之家反转逻辑将延续

2022年&#xff0c;疫情对汽车市场的影响不容忽视。但从财报来看&#xff0c;汽车之家在宏观压力下仍实现了有力的V型反转。 北京时间2月16日美股盘前&#xff0c;汽车之家发布2022Q4及全年财报。财报显示&#xff0c;其四季度实现总营收18.93亿元&#xff0c;同比增长11.8%。…

java并发笔记

文章目录HashMapput方法resize方法ConcurrentHashMapput方法initTable方法sizectl代表什么&#xff1a;扩容计数器ConcurrentHashMap的读操作会阻塞嘛AQS唤醒线程时&#xff0c;AQS为什么从后往前遍历&#xff1f;AQS为什么要有一个虚拟的head节点AQS为什么用双向链表&#xff…

无线网络渗透测试系列学习(一) - 在Windows系统下使用虚拟机安装Kali Linux操作系统

目录 引言&#xff1a; 过程&#xff1a; 配置以及安装VMware虚拟机&#xff1a; 下载Kali Linux的镜像文件&#xff1a; 在虚拟机中打开Kali Linux并执行安装&#xff1a; 配置Kali Linux操作系统&#xff1a; 调整Kal Linux中的时区&#xff1a; 重新设定管理员root的…

Sketch+摹客,100M文件上传最快47s

哈喽&#xff0c;小摹来啦~ 去年12月底&#xff0c;摹客Sketch插件上新了「规范检查工具」&#xff0c;自功能上线以来&#xff0c;小摹收到了许多的好评及赞扬。 虽好评如潮&#xff0c;但我们不会止步不前&#xff0c;将持续攻克难点&#xff0c;旨在为大家提供更加稳定高效…

考公和大厂40万年薪的offer,选哪个?

眼看毕业将至&#xff0c;相信很多小伙伴已经摩拳擦掌&#xff0c;在为毕业季就业做准备了。2023年高校毕业生规模预计1158万人&#xff0c;同比增加82万人。在资深人力资源服务家汪张明看来&#xff0c;2023年的就业态势不仅是大学毕业生数量有增加&#xff0c;还存在一定的存…

开发一个简单易用的SDK的详细步骤(超详细,超适用)

文章目录开发一个简单易用的SDK的详细步骤创建starter步骤关键点总结开发一个简单易用的SDK的详细步骤 创建starter步骤 1.新建一个 spring boot 初始化项目 2.添加依赖&#xff0c;Lombok, Spring Configuration Processor Spring Configuration Processor 的作用是自动生…

2023.2 新方案 java代码混淆 java加密 字符串加密

Java字节码可以反编译&#xff0c;特别是创业公司,很好的项目很容易被别人破解反编译,造成很严重的损失,所以本混淆方案能很好的保护源码,而且在不断迭代,增强混淆效果,异常问题处理,达到保护项目的目的&#xff1a; 本次升级包括: 2023年02年19日 : ht-confusion-project-1.8…

华为云计算之双活容灾

双活&#xff08;HyperMetro&#xff09;本地双活&#xff1a;距离≤10km同城双活&#xff1a;距离&#xff1e;10km没有主备之分&#xff0c;只有本端数据中心和远端数据中心。当一个数据中心的设备故障或数据中心故障&#xff0c;业务会自动切换到另一个数据中心继续运行&…

17_FreeRTOS事件标志组

目录 事件标志组 事件标志组与队列、信号量的区别 事件标志组相关API函数介绍 实验源码 事件标志组 事件标志位:用一个位,来表示事件是否发生 事件标志组是一组事件标志位的集合,可以简单的理解事件标志组,就是一个整数。 事件标志组的特点: 它的每一个位表示一个事件(…

如何效率搭建企业流程系统?试试低代码平台吧

编者按&#xff1a;本文介绍了一款可私有化部署的低代码平台&#xff0c;可用于搭建团队流程管理体系&#xff0c;并详细介绍了该平台可实现的流程管理功能。关键词:可视化设计&#xff0c;集成能力&#xff0c;流程审批&#xff0c;流程调试天翎是国内最早从事快速开发平台研发…

Vscode创建vue项目的详细步骤

目录 一、概述 操作的前提 二、操作步骤 一、概述 后端人员想在IDEA里面创建一个Vue的项目&#xff0c;但是这非常麻烦&#xff0c;用vscode这个前端专用软件创建就会非常快速。 操作的前提 1.安装vscode软件的步骤&#xff1a;vscode下载和安装教程和配置中文插件&#…

分析JEP 290机制的Java实现

简介 https://openjdk.org/jeps/290 Filter Incoming Serialization Data过滤传入的序列化数据 JEP290是Java官方提供的一套来防御反序列化的机制&#xff0c;其核心在于提供了一个ObjectInputFilter接口&#xff0c;通过设置filter对象&#xff0c;然后在反序列化&#xff…