代码之家  ›  专栏  ›  技术社区  ›  Victor Ivens

使用nestjs和multer上载文件

  •  8
  • Victor Ivens  · 技术社区  · 6 年前

    由于nestjs是一款express应用程序,所以可以使用任何库来处理使用nest进行的上传,并且由于它提供了Midlewares,所以也可以使用multer。我的问题是:使用nestjs处理文件上传的最佳方式是什么?

    7 回复  |  直到 6 年前
        1
  •  30
  •   Victor Ivens    6 年前

    由@Kamyl通知 https://github.com/nestjs/nest/issues/262 自从 v4.6.0 可以使用通用文件拦截器使用multer将文件上载到nestjs。

    import { ... , UseInterceptors, FileInterceptor, UploadedFile } from '@nestjs/common'
    
    ... 
    
    @UseInterceptors(FileInterceptor('file'))
    async upload( @UploadedFile() file) {
      console.log(file)
    }
    

    这样,变量 file 将有一个 buffer


    使用Multer选项

    它还需要字段名作为第一个参数,然后是一个带有Multer选项的数组

    import { ... , UseInterceptors, FileInterceptor, UploadedFile } from '@nestjs/common'
    import { diskStorage } from 'multer'
    import { extname } from 'path'
    
    ...
    
    @UseInterceptors(FileInterceptor('file', {
      storage: diskStorage({
        destination: './uploads'
        , filename: (req, file, cb) => {
          // Generating a 32 random chars long string
          const randomName = Array(32).fill(null).map(() => (Math.round(Math.random() * 16)).toString(16)).join('')
          //Calling the callback passing the random name generated with the original extension name
          cb(null, `${randomName}${extname(file.originalname)}`)
        }
      })
    }))
    async upload( @UploadedFile() file) {
      console.log(file)
    }
    

    这样,变量 文件 将有一个 filename , destination path .

    这个 目的地 来自的参数 diskStorage 也可以是一个函数,具有参数,并且期望回调与 文件名 . 通过传递 磁盘存储 文件将自动保存到指定文件名通知的目标。

    还可以通过使用 @UploadedFiles FilesInterceptor (复数)

        2
  •  22
  •   rand0rn    3 年前

    一种更简洁的方法是将配置提取到一个单独的文件中,然后在拦截器方法中调用它

    import { extname } from 'path';
    import { existsSync, mkdirSync } from 'fs';
    import { diskStorage } from 'multer';
    import { v4 as uuid } from 'uuid';
    import { HttpException, HttpStatus } from '@nestjs/common';
    
    // Multer configuration
    export const multerConfig = {
        dest: process.env.UPLOAD_LOCATION,
    };
    
    // Multer upload options
    export const multerOptions = {
        // Enable file size limits
        limits: {
            fileSize: +process.env.MAX_FILE_SIZE,
        },
        // Check the mimetypes to allow for upload
        fileFilter: (req: any, file: any, cb: any) => {
            if (file.mimetype.match(/\/(jpg|jpeg|png|gif)$/)) {
                // Allow storage of file
                cb(null, true);
            } else {
                // Reject file
                cb(new HttpException(`Unsupported file type ${extname(file.originalname)}`, HttpStatus.BAD_REQUEST), false);
            }
        },
        // Storage properties
        storage: diskStorage({
            // Destination storage path details
            destination: (req: any, file: any, cb: any) => {
                const uploadPath = multerConfig.dest;
                // Create folder if doesn't exist
                if (!existsSync(uploadPath)) {
                    mkdirSync(uploadPath);
                }
                cb(null, uploadPath);
            },
            // File modification details
            filename: (req: any, file: any, cb: any) => {
                // Calling the callback passing the random name generated with the original extension name
                cb(null, `${uuid()}${extname(file.originalname)}`);
            },
        }),
    };
    

    然后在拦截器下面这样调用它

    import { ... , UseInterceptors, FileInterceptor, UploadedFile } from '@nestjs/common'
    import { diskStorage } from 'multer'
    import { extname } from 'path'
    import { multerOptions } from 'src/config/multer.config';
    ...
    
    @Post('/action/upload')
    @UseInterceptors(FileInterceptor('file', multerOptions))
    async upload( @UploadedFile() file) {
      console.log(file)
    }
    
        3
  •  5
  •   Nechar Joshi    3 年前

    使用Multer选项的最干净的实现

    感谢您@VictorIvens为我们提供了最好的答案。

    然而 ,我发现了以下内容 问题 在代码中。

    • 导入调用 FileInterceptor 与不存在 @nestjs/common package int-NestJS的最新版本。
    • 代码在我看来有点太乱了。

    所以,到 简化 事情发生了,我想出了以下解决办法。

    存储配置。ts

    export const storage = diskStorage({
      destination: "./uploads",
      filename: (req, file, callback) => {
        callback(null, generateFilename(file));
      }
    });
    
    function generateFilename(file) {
      return `${Date.now()}.${extname(file.originalname)}`;
    }
    
    

    您的控制器。控制器。ts

    import {
      Controller,
      Post,
      UseInterceptors,
      UploadedFile
    } from "@nestjs/common";
    import { FileInterceptor } from "@nestjs/platform-express";
    
    import { diskStorage } from "multer";
    import { extname } from "path";
    import { storage } from "./storage.config"
    
    
    @Controller()
    export class YourController {
      @Post("upload") // API path
      @UseInterceptors(
        FileInterceptor(
          "file", // name of the field being passed
          { storage }
        )
      )
      async upload(@UploadedFile() file) {
        return file;
      }
    }
    
        4
  •  1
  •   Chris Hawkes    3 年前

    **

    2021更新

    **

    现在要这样做,您需要像这样导入FileInterceptor。。。

    import { FileInterceptor } from '@nestjs/platform-express';
    
        5
  •  0
  •   nitin aditya    4 年前

    如果您通过API调用从用户处获取数据,则可以将数据保存为缓冲区,并使用访问内容 adm-zip . 下面是nest中的控制器方法实现。js。

    @Post("/blackBoardUpload")
      @UseInterceptors(
        FileInterceptor('image', {
          storage: memoryStorage(),
    
    
    
          fileFilter: zipFileFilter,
    
        }),
      )
      async uploadedFile(@UploadedFile() file) {
        console.log(file)
        const response = {
          originalname: file.originalname,
          filename: file.filename,
        };
        var AdmZip = require('adm-zip');
        var zip = new AdmZip(file.buffer);
    
        var zipEntries = zip.getEntries();
        console.log(zipEntries.length);
        
        return {
          status: HttpStatus.OK,
          message: 'Received Zip file successfully!',
          data: response,
        };
      }
    
        6
  •  0
  •   vishal sharma    3 年前
        Create a helper.ts file that rename your file and contains path
            
        export class Helper {
                static customFileName(req, file, cb) {
                  const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9);
                  let fileExtension = "";
                  if(file.mimetype.indexOf("jpeg") > -1){
                      fileExtension = "jpg"
                  }else if(file.mimetype.indexOf("png") > -1){
                      fileExtension = "png";
                  }
                  const originalName = file.originalname.split(".")[0];
                  cb(null, originalName + '-' + uniqueSuffix+"."+fileExtension);
                }
               
                static destinationPath(req, file, cb) {
                  cb(null, 'uploads/')
                }
              }
    
    code for controller
    
    import { Helper } from '../service/Helper';
    import { diskStorage } from 'multer';
    import {FileInterceptor} from '@nestjs/platform-express'
    import {Controller, Post, Body, UseInterceptors, UploadedFile} from '@nestjs/common'
    
        @Post('upload')
        @UseInterceptors(
            FileInterceptor('picture', {
                storage: diskStorage({
                    destination: Helper.destinationPath,
                    filename: Helper.customFileName,
                }),
            }),
        )
    
        uploadFile(@UploadedFile() file: Express.Multer.File) {
        console.log(file);
        }
    
        7
  •  -3
  •   Ali Tourani    5 年前

    一种简单的方法是使用控制器。您需要定义上载控制器并将其添加到应用程序中。模块,这是控制器应该是什么的示例(后端):

    @Controller()
    export class Uploader {
      @Post('sampleName')
      @UseInterceptors(FileInterceptor('file'))
      uploadFile(@UploadedFile() file) {
      // file name selection 
        const path = `desired path`;
        const writeStream = fs.createWriteStream(path);  
        writeStream.write(file.buffer);
        writeStream.end();
        return {
          result: [res],
        };
      }
    }
    

    并通过前端提取调用控制器:

        fetch('controller address', {
              method: 'POST',
              body: data,
            })
              .then((response) => response.json())
              .then((success) => {
                // What to do when succeed 
    });
              })
              .catch((error) => console.log('Error in uploading file: ', error));