NestJS Multer Amazon S3会上传多个文件

问题描述 投票:0回答:2

我正在为我的后端使用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属性并将其替换为文件,其中它的值只是文件数组的第一个成员,但这只是为了看看它是否可以工作,如果我发送它预期的东西,但它当时没有用。有没有人对我如何解决这个问题有任何想法?或者任何人都可以通过指向相关教程的链接向我指出正确的方向?

javascript node.js amazon-s3 file-upload nestjs
2个回答
1
投票

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

另外,我正在附上我正在进行文件上传的方式。我只上传单个图片而且我正在使用AWS SDK,因此我不必直接使用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;
      }
    );
}

0
投票

谢谢Jedediah,我喜欢你的代码有多简单。我复制了你的代码,但它仍然没有用。事实证明,在使用accesskey和secretID更新配置后,必须实例化s3对象。

© www.soinside.com 2019 - 2024. All rights reserved.