【问题标题】:NestJS Multer Amazon S3 issues uploading multiple filesNestJS Multer Amazon S3 上传多个文件时出现问题
【发布时间】:2019-02-13 20:59:25
【问题描述】:

我在后端使用 NestJS、Node 和 Express,在前端使用 Angular。我有一个步进器,用户可以在其中逐步输入有关他们自己的信息以及个人资料照片和他们想要发布的任何艺术照片(这是一个草稿)。我正在使用以下代码将文件发送到后端:

<h2>Upload Some Photos</h2>
<label for="singleFile">Upload file</label>

<input id="singleFile" type="file" [fileUploadInputFor]=   "fileUploadQueue"/>
<br>

<mat-file-upload-queue #fileUploadQueue
    [fileAlias]="'file'"
    [httpUrl]="'http://localhost:3000/profile/artPhotos'">

    <mat-file-upload [file]="file" [id]="i" *ngFor="let file of fileUploadQueue.files; let i = index"></mat-file-upload>
</mat-file-upload-queue>

前端将照片作为文件数组发送;我试图改变它,让它只发送一个文件,但无法让它工作。我不太关注这一点,因为用户可能需要上传多个文件,所以无论如何我都想弄清楚。在后端,我使用 multer、multer-s3 和 AWS-SDK 来帮助上传文件,但它不起作用。这是控制器代码:

 @Post('/artPhotos')
    @UseInterceptors(FilesInterceptor('file'))
    async uploadArtPhotos(@Req() req, @Res() res): Promise<void> {
        req.file = req.files[0];
        delete req.files;
        // tslint:disable-next-line:no-console
        console.log(req);
        await this._profileService.fileupload(req, res);
    }

这里是 ProfileService:

import { Profile } from './profile.entity';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { ProfileDto } from './dto/profile.dto';
import { Req, Res, Injectable, UploadedFile } from '@nestjs/common';
import * as multer from 'multer';
import * as AWS from 'aws-sdk';
import * as multerS3 from 'multer-s3';

const AWS_S3_BUCKET_NAME = 'blah';
const s3 = new AWS.S3();
AWS.config.update({
  accessKeyId: 'blah',
  secretAccessKey: 'blah',
});


@Injectable()
export class ProfileService {

  constructor(@InjectRepository(Profile)
  private readonly profileRepository: Repository<Profile> ){}

  async createProfile( profileDto: ProfileDto ): Promise<void> {
    await this.profileRepository.save(profileDto);
  }

  async fileupload(@Req() req, @Res() res): Promise<void> {
    try {
      this.upload(req, res, error => {
        if (error) {
          // tslint:disable-next-line:no-console
          console.log(error);
          return res.status(404).json(`Failed to upload image file: ${error}`);
        }
        // tslint:disable-next-line:no-console
        console.log('error');
        return res.status(201).json(req.file);
      });
    } catch (error) {
      // tslint:disable-next-line:no-console
      console.log(error);
      return res.status(500).json(`Failed to upload image file: ${error}`);
    }
  }

  upload = multer({
    storage: multerS3({
      // tslint:disable-next-line:object-literal-shorthand
      s3: s3,
      bucket: AWS_S3_BUCKET_NAME,
      acl: 'public-read',
      // tslint:disable-next-line:object-literal-shorthand
      key: (req, file, cb) => {
        cb(null, `${Date.now().toString()} - ${file.originalname}`);
      },
    }),
  }).array('upload', 1);
}

我还没有实现任何扩展 multer 的中间件,但我认为我不必这样做。您可以在控制器中看到我删除了 req 上的 files 属性并将其替换为文件,其中它的值只是 files 数组的第一个成员,但这只是为了看看如果我发送它所期望的东西它是否会工作,但它没有工作。有人对我如何解决这个问题有任何想法吗?或者任何人至少可以通过相关教程或其他内容的链接为我指明正确的方向吗?

【问题讨论】:

    标签: javascript node.js amazon-s3 file-upload nestjs


    【解决方案1】:

    我的第一个猜测是您正在使用 FileInterceptor 和 multer。我假设 FileInterceptor 在控制器中添加了 multer,使其可用于 @UploadedFile 装饰器。这可能会导致您以后使用 multer 发生冲突。尝试移除拦截器,看看是否能解决问题。

    我还附上了我是如何进行文件上传的。我只上传单个图像并且我使用的是 AWS 开发工具包,因此我不必直接使用 multer,但这是我的做法,它可能会有所帮助。

    在控制器中:

      @Post(':id/uploadImage')
      @UseInterceptors(FileInterceptor('file'))
      public uploadImage(@Param() params: any, @UploadedFile() file: any): Promise<Property> {
        return this.propertyService.addImage(params.id, file);
    }
    

    然后我的服务

    /**
     * Returns a promise with the URL string.
     *
     * @param file
     */
    public uploadImage(file: any, urlKey: string): Promise<string> {
      const params = {
        Body: file.buffer,
        Bucket: this.AWS_S3_BUCKET_NAME,
        Key: urlKey
      };
    
      return this.s3
        .putObject(params)
        .promise()
        .then(
          data => {
            return urlKey;
          },
          err => {
            return err;
          }
        );
    }
    

    【讨论】:

    • 你传递给uploadImage函数的urlKey是什么?
    • urlKey 是我希望文件在 S3 存储桶中具有的路径和名称。在我的情况下,我生成了一个 UUID,它与我嵌套在其中的一些文件夹一起使用。所以它可能类似于“users/2/0e7b55b7-1e4c-49c4-9a7e-93c526b7fb16”,它将位于“用户”和“2”个文件夹,文件名为“0e7b55b7-1e4c-49c4-9a7e-93c526b7fb16”。
    • 你有什么可以更好地包含上传文件模块的要点吗?我的有很多麻烦
    • @DanutPralea 我不能添加更多内容,但我确实总结了一些要点和更多细节。 gist.github.com/jedsmith13/0c7135ac19af193b893057cf9784550f
    • @JedediahSmith 你能帮我解决这个问题吗?如何将文件作为表单的一部分上传。一旦用户点击提交按钮文件也应该被保存。将永远是伟大的。 stackoverflow.com/questions/69849722/…
    【解决方案2】:

    感谢 Jedediah,我喜欢您的代码如此简单。我复制了您的代码,但它仍然无法正常工作。事实证明,在使用您的 accesskey 和 secretID 更新配置后,您必须实例化 s3 对象。

    【讨论】:

    • 您介意将文件上传模块粘贴到这里还是其他任何地方?我遇到了和你一样的问题,我花了无数个小时试图解决它。
    猜你喜欢
    • 2011-06-09
    • 2020-08-24
    • 1970-01-01
    • 1970-01-01
    • 2018-10-09
    • 2018-10-12
    • 2018-02-01
    • 2018-08-12
    • 1970-01-01
    相关资源
    最近更新 更多