第十九章 Nest multer 文件上传

上章我们了解了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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

tableau数据分层,数据组,与数据集 - 11

tableau数据分层&#xff0c;数据组&#xff0c;与数据集 1. 数据分层1.1 下钻1.2 上钻1.3 创建层级结构1.4 层级排序 2. 数据组2.1 创建分组2.2 编辑组2.3 分组2.4 相关结果2.5 相关例子 3. 静态数据集3.1 数据集相关概念3.2 静态数据集创建方法一3.3 静态数据集创建方法二3.4…

SpringBoot集成Sentinel 实现QPS限流

Spring Cloud Alibaba 的 Sentinel 组件提供了丰富的“流量控制“规则&#xff0c; 单体SpringBoot应用中也可以集成 Sentinel 来实现流量控制&#xff0c;本文主要讲 QPS流量控制。 SpringBoot集成Sentinel有两种方式&#xff1a; 一种是 dashboard控制面板的方式&#xff0…

Java接口案例

一案例要求&#xff1a; 二代码&#xff1a;(换方案只需要将操作类第二行的new新对象修改就能更改项目) Ⅰ&#xff1a;&#xff08;主函数&#xff09; package d1;public class test {public static void main(String[] args) {operator anew operator();a.show();a.averag…

Vue在一个页面调用另一个同级页面的方法

1、建个中转站 2、然后在两个页面都引入它&#xff0c;注意引入路径。 import Utils from src/utils/way 3、调用方的写法 //eg :Utils.$emit(demo, msg) 4、被调用方的写法 //eg :Utils.$on(demo, val>{})

想要制作自己的歌曲伴奏?提取伴奏人声分离软件我用这几款

在音乐制作、翻唱创作或是学术研究等领域&#xff0c;将人声与伴奏分离是一项常见的需求。随着这两年 AI 技术的发展&#xff0c;现在有许多软件和工具可以帮助用户实现这一目标&#xff0c;无需专业的音频编辑知识。本文将重点介绍简鹿人声分离工具以及其他几款知名的人声伴奏…

数据库第四次练习

数据准备 创建两张表&#xff1a;部门&#xff08;dept&#xff09;和员工&#xff08;emp&#xff09;&#xff0c;并插入数据&#xff0c;代码如下 create table dept( dept_id int primary key auto_increment comment 部门编号, dept_name char(20) comment 部门名称 ); in…

全现金!6.65亿美刀!AMD大手一挥收购欧洲最大私人AI实验室

当地时间2024年7月10日&#xff0c;AMD宣布&#xff0c;他们刚刚签署了一项最终协议&#xff0c;豪掷6.65亿美刀收购欧洲最大的私人人工智能实验室Silo AI&#xff0c;而且还是全现金收购&#xff01; 据AMD官网报道&#xff0c;该协议代表着该公司基于开放标准并与全球人工智…

IAR全面支持芯驰科技E3系列车规MCU产品E3119/E3118

中国上海&#xff0c;2024年7月11日 — 全球领先的嵌入式系统开发软件解决方案供应商IAR与全场景智能车芯引领者芯驰科技宣布进一步扩大合作&#xff0c;最新版IAR Embedded Workbench for Arm已全面支持芯驰科技的E3119/E3118车规级MCU产品。IAR与芯驰科技有着悠久的合作历史&…

【精简教程】VSCode 连接 Remix

初始化 Node.js 项目 yarn init v1.22.19安装 Remix yarn add remix-project/remixd -g⚠️ 此时如果直接敲 remix&#xff0c;显示找不到这个命令。 使用 Node.js 来直接执行 remixd.js 文件 node node_modules\remix-project\remixd\src\bin\remixd.js&#x1f604; 连接上了…

tasking软件许可优化解决方案

Tasking软件介绍 TASKING SmartCode是用于英飞凌下一代AURIX™ TC4x微控制器家族的开发解决方案。SmartCode产生快速并且紧凑的代码&#xff0c;是唯一全面支持TC4x全部架构和内核的软件开发平台。英飞凌AURIXTM提供了实现ECU所需的处理能力、外设支持和安全/安全机制。 所有开…

独立站营销新思路:携手TikTok达人,促进用户参与与品牌传播

数字化时代&#xff0c;品牌传播的方式发生了重大变化。尤其是TikTok&#xff0c;作为全球最受欢迎的短视频平台之一&#xff0c;其独特的社群特点和用户行为模式&#xff0c;对品牌独立站提供了全新的营销思路。本文Nox聚星将和大家分析TikTok社群的特点和用户行为模式&#x…

let/const/var的区别及理解

在JavaScript中&#xff0c;let、const 和 var 是用来声明变量的关键字&#xff0c;但它们之间在作用域、变量提升、重复声明等方面存在区别&#xff0c;详细情况如下: 1. let、const、var 的区别 (1) 块级作用域 let 和 const&#xff1a;具有块级作用域&#xff0c;由 {} 包…

pico+unity3d搭建环境

分别注册pico开发者平台和unity的账号密码 下载pico的sdk和unity开发软件 创建unity3d核心项目 在项目中找到窗口&#xff0c;包管理器&#xff0c;添加磁盘的包&#xff0c;选中sdk 安装后就可以使用pico的操作和演示&#xff1b; 剩下的看文档

JVM:类加载器

文章目录 一、什么是类加载器 一、什么是类加载器 类加载器&#xff08;ClassLoader&#xff09;是Java虚拟机提供给应用程序去实现获取类和接口字节码数据的技术。类加载器只参与加载过程总的字节码获取并加载到内存这一部分。

中职网络安全B模块渗透测试server2380

使用nmap扫描添加参数-sV Flag:2.4.38 添加参数-A不然扫不全 &#xff08;这两题可以直接加-sV -A&#xff09; Flag: 4.3.11-Ubuntu 根据nmap扫描发现系统为ubuntu系统&#xff0c;ubuntu操作系统在某些版本中默认包含一个名为"ubuntu"的用户帐户。这是为了方…

电脑硬盘分区及合并指南

电脑硬盘分区是指将一个硬盘划分成多个独立的区域&#xff0c;每个区域可以被操作系统单独管理和使用&#xff0c;我们可以根据需要将数据分类存储&#xff0c;例如将系统文件、个人文件和多媒体内容分别存放在不同的分区中。合理的分区不仅可以提升系统性能&#xff0c;还能提…

硬盘模式vmd怎么改ahci_电脑vmd改ahci模式详细步骤

最近有很多网友问&#xff0c;我新买的电脑安装原版win10或win11找不到驱动器呀&#xff0c;进入第三方pe又找不到硬盘&#xff0c;找到硬盘安装后又出现安装蓝屏的情况&#xff0c;新机器怎么回事呀&#xff1f;这位网友内心有点崩溃&#xff0c;不知道啥原因。其实这些都是由…

洛谷P1498 南蛮图腾[递归好题]

南蛮图腾 题目背景 自从到了南蛮之地&#xff0c;孔明不仅把孟获收拾的服服帖帖&#xff0c;而且还发现了不少少数民族的智慧&#xff0c;他发现少数民族的图腾往往有着一种分形的效果&#xff0c;在得到了酋长的传授后&#xff0c;孔明掌握了不少绘图技术&#xff0c;但唯独…

金龙鱼:只是躺枪?

中储粮罐车运输油罐混用事件持续发酵&#xff0c;食用油板块集体躺枪。 消费者愤怒的火&#xff0c;怕是会让食用油企们一点就着。 今天&#xff0c;我们聊聊“油”茅——金龙鱼。 一边是业内人士指出&#xff0c;油罐混用的现象普遍存在&#xff0c;另一边是金龙鱼回应称&am…

【Linux】进程的基本概念(以及进程地址空间的初步了解)

目录 一.什么是进程 进程和程序的区别 Linux查看进程 进程的信息 fork函数 二.进程状态 操作系统上进程状态的概念 运行 阻塞 挂起 Linux中的进程状态 R状态 S状态和D状态 T状态 t状态 X状态 Z状态 三.进程的优先级 修改进程优先级 四.环境变量 常见的环境变量 PATH HOME PW…