代码之家  ›  专栏  ›  技术社区  ›  Dimuthu Lakmal

NestJS本身不支持流文件上传

  •  0
  • Dimuthu Lakmal  · 技术社区  · 11 月前

    这里有两个JavaScript脚本:一个用于服务器,一个用于客户端。这些脚本使用流而不是将文件转换为表单数据来促进文件上传。然而,由于NestJS本身不支持这种类型的文件上传,如何在NestJS应用程序中实现这一点?我可以考虑的其他选择是什么?

    server.js

    import { createWriteStream } from "node:fs";
    
    import http from "node:http";
    
    function respond(res, code, message) {
      res.writeHead(code, {
        "Content-Type": "text/plain",
    
        "Content-Length": message.length,
      });
    
      res.end(message);
    }
    
    const server = http.createServer(async (req, res) => {
      if (req.method === "POST") {
        const filename = req.headers["content-disposition"].match(/"(.*)"/)[1];
    
        const file = createWriteStream(`Received-${filename}`);
    
        req.pipe(file);
    
        req.on("end", () => {
          respond(res, 200, "Thanks");
        });
      } else {
        respond(res, 200, "Hi");
      }
    });
    
    server.on("error", (err) => {
      console.log(err.stack);
    });
    
    server.on("clientError", (err, socket) => {
      if (err.code === "ECONNRESET" || !socket.writable) {
        return;
      }
    
      socket.end("HTTP/1.1 400 Bad Request\r\n\r\n");
    });
    
    server.on("listening", () => {
      console.log("Server started on http://localhost:8080");
    });
    
    server.listen(8080);
    
    

    client.js

    import { createReadStream } from "node:fs";
    
    async function upload(filename) {
      const res = await fetch("http://localhost:8080", {
        method: "POST",
    
        headers: {
          "Content-Disposition": `attachment; filename="${filename}"`,
        },
    
        duplex: "half",
    
        body: createReadStream(filename),
      });
    
      return res.ok;
    }
    
    console.log(await upload("TestVideo.mp4"));
    
    1 回复  |  直到 11 月前
        1
  •  1
  •   Architect - Hitesh    11 月前

    为了在NestJS应用程序中实现流式文件上传,您可以利用底层HTTP模块(类似于Node.js HTTP服务器示例),同时将其集成到NestJS中。您可以这样做:

    设置一个基本的NestJS应用程序

    npm i -g @nestjs/cli
    nest new file-upload-stream
    

    安装所需依赖项

    npm install @nestjs/common @nestjs/core @nestjs/platform-express rxjs
    npm install --save-dev @types/node
    

    文件上传控制器

    import { Controller, Post, Req, Res } from '@nestjs/common';
    import { Request, Response } from 'express';
    import { createWriteStream } from 'fs';
    import { pipeline } from 'stream';
    import { promisify } from 'util';
    
    const pump = promisify(pipeline);
    
    @Controller('upload')
    export class UploadController {
      @Post()
      async uploadFile(@Req() req: Request, @Res() res: Response) {
        const filename = req.headers['content-disposition']?.match(/filename="(.+)"/)?.[1];
        if (!filename) {
          res.status(400).send('Missing filename in Content-Disposition header');
          return;
        }
    
        const filePath = `./Received-${filename}`;
        const fileStream = createWriteStream(filePath);
    
        try {
          await pump(req, fileStream);
          res.status(200).send('File uploaded successfully');
        } catch (err) {
          console.error(err);
          res.status(500).send('File upload failed');
        }
      }
    }
    

    在模块中注册控制器

    import { Module } from '@nestjs/common';
    import { UploadController } from './upload.controller';
    
    @Module({
      controllers: [UploadController],
    })
    export class UploadModule {}
    

    然后在应用程序模块中注册它

    import { Module } from '@nestjs/common';
    import { UploadModule } from './upload/upload.module';
    
    @Module({
      imports: [UploadModule],
    })
    export class AppModule {}
    

    更新main.ts

    import { NestFactory } from '@nestjs/core';
    import { AppModule } from './app.module';
    
    async function bootstrap() {
      const app = await NestFactory.create(AppModule);
      await app.listen(3000);
    }
    
    bootstrap();
    

    客户端脚本

    import { createReadStream } from 'node:fs';
    
    async function upload(filename) {
      const res = await fetch('http://localhost:3000/upload', {
        method: 'POST',
        headers: {
          'Content-Disposition': `attachment; filename="${filename}"`,
        },
        duplex: 'half',
        body: createReadStream(filename),
      });
    
      return res.ok;
    }
    
    console.log(await upload('TestVideo.mp4'));
    

    您还可以使用multer中间件,还可以对文件大小和文件类型进行验证