将图像直接从 Angular 应用程序上传到 AWS S3

Upload images directly from an Angular application to AWS S3

我目前正在按照 this 教程将图像直接从我的 angular 应用程序上传到 AWS S3 存储桶。我做了一些小改动,以解决执行过程中出现的一些错误,但是当我 运行 我的代码时,我发现我使用的函数 select 图像 ("select File()") 在我点击按钮时没有被执行。

我的appcomponent.ts文件中的代码如下:

export class AppComponent {
  selectedFiles: any = '';  //In the tutorial it was selectedFiles: FileList; But it kept throwing errors.
  imageSrc: string = '';

  constructor(private uploadService: UploadService) { }
  
  ngOnInit() {
  }
  
  upload() {
    const file = this.selectedFiles.item(0);
    this.uploadService.uploadFile(file);
  }
  
  selectFile(event: any) {
    const reader = new FileReader();
    if(event.target.files && event.target.files.length) {
      const [file] = event.target.files;
      console.log(file.name);
      reader.readAsDataURL(file);
      reader.onload = () => {
        this.imageSrc = reader.result as string;
      }
      this.selectedFiles = file;
    }
  }
}

上传服务:

import { Injectable } from '@angular/core';
import * as AWS from 'aws-sdk/global';
import * as S3 from 'aws-sdk/clients/s3';

@Injectable({
  providedIn: 'root'
})
export class UploadService {

  constructor() { }

  uploadFile(file: any) {
    const contentType = file.type;
    const bucket = new S3({
      accessKeyId: '...',
      secretAccessKey: '...',
      region: '...'
    });
    const params = {
      Bucket: '...',
      Key: file.name,
      Body: file,
      ACL: 'public-read',
      ContentType: contentType
    };
    bucket.upload(params, function(err: any, data: any){
      if (err) {
        console.log('There was an error uploading your file: ', err);
        return false;
      }
      console.log('Successfully uploaded file.', data);
      return true;
    });
    //for upload progress   
    /*bucket.upload(params).on('httpUploadProgress', function (evt) {
        console.log(evt.loaded + ' of ' + evt.total + ' Bytes');
      }).send(function (err, data) {
      if (err) {
        console.log('There was an error uploading your file: ', err);
        return false;
      }
      console.log('Successfully uploaded file.', data);
      return true;
    });*/
  }
}

下面是AppComponent.html:

<label class="btn btn-default">
  <img [src]="imageSrc" *ngIf="imageSrc" style="width:100%">
  <input type="file" (change)="selectFile($event)">
</label>

<button class="btn btn-success" [disabled]="!selectedFiles" (click)="upload()">Upload</button>

我哪里错了?

您两次从文件列表中取出第一个文件:

const [file] = event.target.files; // taking the first file

然后在 upload 函数中再次:

const file = this.selectedFiles.item(0);

此外,您似乎在混合 this.selectedFiles(名称和您的教程暗示应该是文件列表,并且出于某种原因您将其初始化为空字符串!)和您在 selectFile.

中分配给它类型文件

我认为使用强类型会更好,我将更改 .html 和 .ts,如下所示:

.html:

<label class="btn btn-default">
  <img [src]="imageSrc" *ngIf="imageSrc" style="width:100%">
  <input type="file" (change)="selectFile($event.target.files)">
</label>

<button class="btn btn-success" [disabled]="!selectedFileToUpload" (click)="upload()">Upload</button>

和.ts:

private selectedFileToUpload: File = null;

public upload() {
    if (!this.selectedFileToUpload) {
        alert('Please select a file first!'); // or any other message to the user to choose a file
        return;
    }

    this.uploadService.uploadFile(this.selectedFileToUpload);
}

public selectFile(filesList: FileList) {
    var reader = new FileReader();

    const fileToUpload = filesList.item(0);

    console.log(fileToUpload.name);
    reader.readAsDataURL(fileToUpload);
    reader.onload = () => {
        this.imageSrc = reader.result as string;
    };

    this.selectedFileToUpload = fileToUpload;
}

注意,

however when I run my code I find that the function I use to select the image ("selectFile()") is not being executed when I click the button.

单击上传按钮时不应执行selectFile函数! selectFile 函数将在您每次更改所选文件中的文件时执行,并且在我编写的示例(未测试)中它应该保存对您要上传的文件的引用。然后,Upload 按钮只会触发 upload 函数,该函数会对所选文件进行相同的引用,并将其传递给上传服务,由 s3 包上传。

同样,我没有测试代码,但我试图通过修复您的逻辑来提供帮助。