使用相机和文件插件在 Ionic 4 中上传图片

Picture upload in Ionic 4 with camera and file plugins

我正在尝试将 Ionic 4 中的文件上传到服务器,但出现错误 2nd parameter must be blob

但我已经记录了 blob 图像,它正在正常运行。

我在这个 https://devdactic.com/ionic-4-image-upload-storage/ 这个 link 中关注这个指南。

我不需要将其保存到本地存储,因此我跳过了该部分。

selectImageInGallery() {
    const options: CameraOptions = {
      quality: 100,
      sourceType: this.camera.PictureSourceType.PHOTOLIBRARY,
      destinationType: this.camera.DestinationType.FILE_URI,
      encodingType: this.camera.EncodingType.JPEG,
      mediaType: this.camera.MediaType.PICTURE,
      saveToPhotoAlbum: false
    };
    this.camera.getPicture(options).then(
      imageData => {
        const formData = this.uploadAvatar(imageData);
        this.uploadAvatar(formData);
      },
      err => {
        this.toastService.presentToastBottom('Failed to select the image');
      }
    );
  }

uploadAvatar(imagePath: any) {
    let fileName = '';
    this.file
      .resolveLocalFilesystemUrl(imagePath)
      .then(fileEntry => {
        const { name, nativeURL } = fileEntry;
        const path = nativeURL.substring(0, nativeURL.lastIndexOf('/'));
        fileName = name;
        return this.file.readAsArrayBuffer(path, name);
      })
      .then(buffer => {
        const imgBlob = new Blob([buffer], {
          type: 'image/jpeg'
        });
        console.log(imgBlob);
        const formData: FormData = new FormData();
        formData.append('avatar', imgBlob);
        this.userService.updateAvatar(formData).then(res => {
          console.log(res);
          this.loader.hideLoader();
          // if (res.data.status === 'success') {
          //   this.user = res.data.user;
          // } else if (res.data.status === 'error') {
          //   this.toastService.presentToast(res.data.message);
          // } else {
          //   this.toastService.presentToast('Server Error');
          // }
        });
      });
  }

Service
public async updateAvatar(postData: any) {
    const httpOptions = {
      headers: new HttpHeaders({
        'Content-Type': 'multipart/form-data',
        'X-Authorization': environment.appKey,
        Authorization: localStorage.getItem('TOKEN_KEY')
      })
    };
    const res = await this.http
      .post(
        environment.apiUrl + 'user/update-profile-picture',
        postData,
        httpOptions
      )
      .toPromise();
    return res as any;
  }

您对本教程的了解程度如何?

我记得看过 Simon 的视频(devdactic 作者),处理图像有一些复杂的地方,您需要在系统上至少创建一个临时文件才能发送到其他地方。

首先,您应该完全按照教程进行操作,然后一旦它起作用,您就可以尝试删除一些东西。

在教程的第一部分中明确指出:

  • 使用 POST 请求
  • 从他们的 本地路径 上传文件

因此,我认为仅删除教程的大块内容并不是实现这一目标的最佳方法。

先向专家学习,再修改。

    uploadBase64(imageBase64: any) {
    this.loader.showLoader();
    const blobImg = this.dataURItoBlob(imageBase64);
    const formData: FormData = new FormData();
    formData.append('avatar', blobImg, 'image.jpeg');
    this.profileService.updateAvatar(formData).then(res => {
      this.loader.hideLoader();
      if (res.data.status === 'success') {
        this.user.avatar = imageBase64;
      } else if (res.data.status === 'error') {
        this.toastService.presentToast(res.data.message);
      } else {
        this.toastService.presentToast('Server Error');
      }
    });
  }

  dataURItoBlob(dataURI: any) {
    // convert base64/URLEncoded data component to raw binary data held in a string
    let byteString: any;
    if (dataURI.split(',')[0].indexOf('base64') >= 0) {
      byteString = atob(dataURI.split(',')[1]);
    } else {
      byteString = unescape(dataURI.split(',')[1]);
    }
    // separate out the mime component
    const mimeString = dataURI
      .split(',')[0]
      .split(':')[1]
      .split(';')[0];
    // write the bytes of the string to a typed array
    const ia = new Uint8Array(byteString.length);
    for (let i = 0; i < byteString.length; i++) {
      ia[i] = byteString.charCodeAt(i);
    }
    return new Blob([ia], { type: mimeString });
  }

  async openCertificateUploadPage() {
    const modal = await this.modalCrtl.create({
      component: CertificateUploadPage
    });
    modal.onDidDismiss().then(res => {
      this.getProfile();
    });
    return await modal.present();
  }

这就是该问题的解决方案。我想通了。