firebase AngularFireStorage是否上传多个图像?

cclgggtu  于 2022-11-25  发布在  Angular
关注(0)|答案(2)|浏览(286)

我正在使用Angularfire2指南上传图片:https://github.com/angular/angularfire2/blob/master/docs/storage/storage.md
我已经把它付诸实践,我已经设法上传,但只有一个图像每个行动。是否有可能加载多个图像?我如何才能做到这一点?
component.ts

import { Component, OnInit } from '@angular/core';
import { AngularFireStorage } from 'angularfire2/storage';
import { Observable } from '../../../../node_modules/rxjs';
import { finalize } from 'rxjs/operators';

@Component({
selector: 'app-root',
template: `
  <input type="file" (change)="uploadFile($event)" />
  <div>{{ uploadPercent | async }}</div>
  <a [href]="downloadURL | async">{{ downloadURL | async }}</a>
`
})

export class AppComponent {

uploadPercent: Observable<number>;
downloadURL: Observable<string>;

constructor(private storage: AngularFireStorage) {}

uploadFile(event) {
  const file = event.target.files[0];
  const filePath = 'name-your-file-path-here';
  const fileRef = this.storage.ref(filePath);
  const task = this.storage.upload(filePath, file);

  // observe percentage changes
  this.uploadPercent = task.percentageChanges();
  // get notified when the download URL is available
  task.snapshotChanges().pipe(
    finalize(() => this.downloadURL = fileRef.getDownloadURL() )
 )
.subscribe()
}
}
mnemlml8

mnemlml81#

对于未来的读者,这里是我如何解决多个图像上传使用Angular 8和Firebase后挣扎了几天:

export class AppComponent {

 uploadPercent: Observable<number>;
 downloadURL: Observable<string>;

 uploads: any[]; // an array that holds the uploaded image URLs and refs

constructor(private storage: AngularFireStorage) {}

uploadFile(event) {
  this.uploads = [];
  const filelist = event.target.files;

  for (const file of filelist) {
    const path = `product-images/${file.name}`;
    const ref = this.storage.ref(path);
    const task = this.storage.upload(path, file);
    //the percentage is still not 100% working as it should
    this.uploadPercent$ = task.percentageChanges();

    // for every upload we will store the image URL in this.uploads array
    const _t = task.then((f) => {
     return f.ref.getDownloadURL().then((imageURLs) => {        
      this.uploads.push(imageURLs);
    })
  });
  }

  
 //we return a promise after making sur all images has been uploaded
 return new Promise(async (resolve, reject) => {
  const run = async () => {
   if (this.uploads.length === filelist.length) {
     console.log("All image has been uploaded")
     resolve(this.uploads);
   } else {
     console.log(uploads.length + '/' + filelist.length + ' images has been uploaded..')

    //We check every 500ms if all the image has been uploaded, otherwise we try check again
     return this.delay(500).then(run);
   }
 }
 return this.delay(500).then(run);
 }) 
}

private delay(t) {
  return new Promise(resolve => {
    setTimeout(resolve, t);
  });
 }
}

我知道有一个使用RXJS进行异步调用的替代方法,但是我不能让它工作。这就是为什么我实现了deley()函数。

d8tt03nd

d8tt03nd2#

这是我如何处理上传多个文件到firebase云存储
1.创建接受上传文件夹/路径和要上传的文件数组的功能/服务
1.让函数使用[文件路径+日期时间+文件索引]为每个文件创建一个唯一的文件名,使用MD5散列或任何您喜欢的库。
1.创建一个主题/可观察对象以返回上载的状态。每个上载的文件在完成或出错时更新此主题
1.返回作为可观察流的主题,以订阅多个上传的结果

定义接口

export interface iImageUploadsResult{
file: File;
index: number;
successful: boolean;
downloadUrl?: string;
error?: any
};

export interface iImageUploadsResults{
fileCount: number;
uploadCount: number;
failedCount: number;
completed: boolean;
results: iImageUploadsResult[]
}

上传多个图像功能

uploadMultipleImages(path: string, files: File[], metaData: any){
    const md5 = new Md5();
    const date = new Date().toDateString();

    //Create a stream of upload results for the multiple files. update the stream any time a file is uploads or fails
    const uploadResultsSubject: BehaviorSubject<iImageUploadsResults> = new BehaviorSubject<iImageUploadsResults>({} as iImageUploadsResults);
    uploadResultsSubject.next({completed: false, fileCount: files.length, uploadCount: 0, failedCount:0, results: []}); // Set initial state... isolated for readability

    files.map((file, index) => {
      // Create a unique hash From {Path/datetime/indexOfFile}
     md5.appendStr(path).appendStr(date).appendStr(String(index));
     const filename = md5.end();
     //console.log({filename}) // 1931b9e7b180ab6ace13689d44250712

      const ext = file.type.split('/')[1] //Get file extension
      // Create full file reference from {path/hash.ext}
      const imageRef = ref(this.storage, `${path}/${filename}.${ext}`);

      // Start individual file upload
      const uploadTask = uploadBytes(imageRef, file, {customMetadata: metaData}).then(
        (results) => {
          // Obtain URL of upload file and update resultsStream i.e. [uploadResultsSubject]
          return getDownloadURL(results.ref).then((downloadURL) => {
            const uploadState = uploadResultsSubject.value; //current state of subject
            const uploadResult: iImageUploadsResult = {
              file,
              index,
              successful : true,
              downloadUrl: downloadURL
            }

            // Updating subject or stream
            uploadState.results?.push(uploadResult);
            uploadState.uploadCount++;
            uploadState.completed = uploadState.fileCount === uploadState.uploadCount? true : false;
            uploadResultsSubject.next(uploadState);

            return uploadState;
          });
        }
      ).catch(err => { //On error, update subject or stream

        const uploadState = uploadResultsSubject.value;
        const uploadResult: iImageUploadsResult = {
          file,
          index,
          successful: false,
          error: err
        }

        uploadState.results?.push(uploadResult);
        uploadState.uploadCount++;
        uploadState.failedCount++;
        uploadState.completed = uploadState.fileCount === uploadState.uploadCount? true : false;
        uploadResultsSubject.next(uploadState);
      })

    });

    // return Observable of file upload results.
    // When [mageUploadsResults].completed === true. then upload is complete
    // Use  [mageUploadsResults].failedCount for number of failed uploads
    // Use  [mageUploadsResults].results for details of each file upload including downloadUrl
    return uploadResultsSubject.asObservable().pipe(distinctUntilChanged())

  }

您还可以将用户唯一ID添加到MD5哈希中,以确保用户名和文件名在任何时间点都不会相同。

如何调用/使用

uploadMultipleImages(
    `products/shop/product`, //path or directory
    files, //Files[]
    {shopId: '', productid:''} //Metadata
    ).subscribe(results => {
      console.log(results)
      // {
      //   completed: true,
      //   failedCount: 0,
      //   fileCount: 6,
      //   results: (6) [{…}, {…}, {…}, {…}, {…}, {…}],
      //   uploadCount: 6
      // }

    });

您可以根据需要修改接口和结构,以返回所需的任何数据

相关问题