当前位置: 首页 > 知识库问答 >
问题:

如何上传照片到Firebase存储和插入照片URL在Firestore?

乐正晟
2023-03-14

我在这个模块中的主要目标是将用户的个人资料图片上传到Firebase存储库中,并将照片URL存储到Firestore(云Firestore)中。

注:

  1. 我上载的图像只有JPG和PNG格式。
  2. 这是跨平台应用程序,使用离子和角
    null

  userId: string;
  fname: string;
  studentId: string;


  @ViewChild('filePicker') filePickerRef: ElementRef<HTMLInputElement>;
  @Input() showPreview = true;

  //The Selected Image in the File Explorer
  selectedImage: any;


   constructor(private auth: AuthService,
              private afs: AngularFirestore,
              private loadingCtrl: LoadingController,
              private toaster: ToastController,
              private storage: AngularFireStorage,
              private popOverCtrl: PopoverController) { }

  ngOnInit() {

    this.profileEditSub = this.auth.user$.subscribe(user => {
      this.userId = user.userId;
      this.fname = user.userName;
      this.studentId = user.userSchoolId;
      this.selectedImage = user.userPhoto;
    });

  }

  onSubmit(form: NgForm){

    const user = form.value.fname;
    const studentId = form.value.studentId;

    this.onUpdateUser(user, studentId);

  }//

  async onUpdateUser(name: string, studentNo: string){
    const loading = await this.loadingCtrl.create({
      message: 'Updating...',
      spinner: 'crescent',
      showBackdrop: true
    });

    
    loading.present();
    
    const imageUrl = await this.uploadFile(this.userId, this.selectedImage);

    this.afs.collection('user').doc(this.userId).update({
      'userName': name,
      'userSchoolId': studentNo,
      'userPhoto': imageUrl, // Photo URL from Firebase Storage will be saved in here.
      'editedAt': Date.now()
    })
    .then(() => {
      loading.dismiss();
      this.toast('Update Success', 'success');
      this.closePopOver();
    })
    .catch(error => {
      loading.dismiss();
      this.toast(error.message, 'danger');
    })

  }//

  async uploadFile(id, files):Promise<any> {
    if (files && files.length) {
      try {
        const task = await this.storage.ref('images').child(id).put(files[0]);
        return this.storage.ref(`images/${id}`).getDownloadURL().toPromise();
      } catch (error) {
        console.log(error);
      }
    }
  }

  onPickImage() {
    this.filePickerRef.nativeElement.click();
  }

  onFileChosen(event: Event) {
    const pickedFile = (event.target as HTMLInputElement).files[0];

    if (!pickedFile) {
      return;
    }

    const fr = new FileReader();
    fr.onload = () => {
      const dataUrl = fr.result.toString();
      this.selectedImage = dataUrl;
    
    };
    fr.readAsDataURL(pickedFile);
  }

update-profile.component.html

  <!-- For the Image -->
  <div class="picker">
    <img
      class="img"
      [src]="selectedImage"
      *ngIf="selectedImage && showPreview"
    >
  </div>
  <input type="file" accept=".jpg,.png" *ngIf="usePicker" #filePicker (change)="onFileChosen($event)"/>

  <ion-button class="image-btn" (click)="onPickImage()">
    <ion-icon name="camera" slot="icon-only"></ion-icon>
  </ion-button>

  <!-- Other Textual Information -->
  <form #f="ngForm" (ngSubmit)="onSubmit(f)">
    <ion-list lines="full">
      <ion-item>
        <ion-label position="floating">Full Name:</ion-label>
        <ion-input name="fname" required type="text" [(ngModel)]="fname" #userCtrl="ngModel"></ion-input>
      </ion-item>
      <ion-item>
        <ion-label position="floating">Student No:</ion-label>
        <ion-input name="studentId" required type="number" [(ngModel)]="studentId" #studentIds="ngModel"></ion-input>
      </ion-item>

      <ion-button class="ion-margin" type="submit" expand="block" shape="round" [disabled]="!f.valid">Edit User</ion-button>
    </ion-list>
  </form>

共有1个答案

欧阳安晏
2023-03-14

在您的代码中,我注意到了一些事情。

  1. 您打算在标记的选定文件上使用this.selectedimage变量(来自文件资源管理器的注释),但在下面的行中,您将其重新分配到FireStore中图像的存储引用。
this.profileEditSub = this.auth.user$.subscribe((user) => {
  ...
  this.selectedImage = user.userPhoto; // this line
});

>

  • src使用单独的变量,然后使用另一个变量存储文件选取器的当前值()。

    update-profile.component.ts

    currentImageUrl: string; // to store the downloadUrl of image to be displayed
    selectedFiles: Array<File>; // to store selected files in the File Explorer
    
    this.profileEditSub = this.auth.user$.subscribe(async (user) => {
      ...
    
      /** 
       * you only store the storage reference (user.userPhoto) in firestore, not the download url,
       * so you need to fetch it again
       */
      this.currentImageUrl = await this.storage
        .ref(user.userPhoto)
        .getDownloadURL()
        .toPromise();
    });
    
    onFileChosen(event: any) {
        this.selectedFiles = event.target.files; // just assigns the selected file/s in <input> this.selectedFiles
    }
    
    async onSubmit() {
        if (this.selectedFiles.length) {
            // Get selected file
            const file = this.selectedFiles[0];
    
            // Get the fullPath in Storage after upload
            const fullPathInStorage = await this.uploadImage(this.userId, file);
    
            /**
             * You can now store the fullPathInStorage in firestore
             *
             * afs.update(...)
             */
    
            // Get the downloadUrl for the src of img
            this.currentImageUrl = await this.storage
                .ref(fullPathInStorage)
                .getDownloadURL()
                .toPromise();
        }
    }
    
    async uploadImage(uid, file): Promise<string> {
        /**
         * You can add random number in file.name to avoid overwrites,
         * or replace the file.name to a static string if you intend to overwrite
         */
        const fileRef = this.storage.ref(uid).child(file.name);
    
        // Upload file in reference
        if (!!file) {
          const result = await fileRef.put(file);
    
          return result.ref.fullPath;
        }
    }
    

    update-profile.component.html

    <input type="file" (change)="onFileChosen($event)"/>
    
    <img [src]="currentImageUrl" />
    

    此外,err_name_not_resolved可能只是由于网络不稳定。

  •  类似资料:
    • 我试图构建一个,它包括两个按钮,一个用于用相机拍照并上传到Firebase存储,另一个用于从Firebase存储下载图像并在上显示。 现在,我被上传功能卡住了。我可以把照片保存到应用程序目录中。我想上传保存的图片到Firebase存储。

    • 我正试着上传一张照片,在被croppie剪切到GCS之后。gcs write(imageToUpload)方法失败,因为imageToUpload当前不是文件,而是Blob。有没有人知道一个办法让这件事成功?可能是python中一种将BLOB转换为文件的方法吗?可以从Croppie返回的图像类型有:1)画布,2)HTML,3)BLOB和4)Base64这里是文档(Ctrl-F“result”)。任

    • 我试图获得这样的下载网址,但它没有得到正确的网址。我是Firebase的初学者,怎么做呢?

    • 我尝试了DPZFlickr,它在尝试上传时返回以下内容: 检查Flickr API的响应,它与尝试Dantsu版本的phpFlickr时返回的结果相同,返回如下: 我卷了自己的卷曲,返回如下:

    • 我收到代码为200的响应,但图像没有上传到服务器

    • 操作步骤: ①在"图层管理"模块,选择一个带有数据的图层。 ②点击记录弹出窗口。 ③点击"上传图片"按钮。 ④可以添加标注地点的照片信息,支持从本地上传和选择网络上的图片以及历史图片。 ⑤选择图片,进行添加图片。 ⑥点击"绑定图片"按钮。 提示: ●目前一个网点支持上传20张照片。 ●每张图片大小不超过5M。 操作动图: [查看原图]