ionic 3 загружает изображение с камеры, НЕ ИСПОЛЬЗУЯ плагины для файлов, передачи файлов и загрузки файлов

Я хотел бы загрузить изображение на свой сервер с помощью FormData, но поскольку Ionic DEVAPP и Ionic VIEW не поддерживают плагины для файлов, передачи файлов и загрузки файлов, мне нужно сделать это, используя только Angular Http или HttpClient.

При использовании DestinationType.FILE_URI я могу получить внутренний URL-адрес из файла и отобразить его на объекте img, но я не могу создать объект TypeScript File из этого URL-адреса без собственного файла, пути к файлу и плагинов для передачи файлов.

getImage() {
const options: CameraOptions = {
  quality: 100,
  destinationType: this.camera.DestinationType.FILE_URI,
  sourceType: this.camera.PictureSourceType.PHOTOLIBRARY
}

this.camera.getPicture(options).then((imageData) => {
  this.imageURI =  this.sanitizer.bypassSecurityTrustUrl(imageData)
}, (err) => {
  console.log(err)
  this.presentToast(err)
})

}

используя этот шаблон

<ion-content padding>
  <ion-item>
    <p>{{imageFileName}}</p>
    <button ion-button color="secondary" (click)="getImage()">Get Image</button>
  </ion-item>
  <ion-item>
    <h4>Image Preview</h4>
    <img style="display:block" [src]="imageURI" *ngIf="imageURI" alt="Ionic File" width="300" />
  </ion-item>
  <ion-item>
    <button ion-button (click)="uploadFile()">Upload</button>
  </ion-item>
</ion-content>

При использовании DestinationType.DATA_URL я могу отобразить изображение, но не могу создать объект TypeScript File, необходимый с исходным именем файла, чтобы добавить изображение к FormData, используемому в моей службе загрузки в моем Ionic App.

Кажется, я могу найти способ создать этот объект TypeScript File с исходным именем файла из FILE_URI и данными в кодировке base64 из DATA_URL, используя camera.getPicture из собственного плагина камеры cordova.

Сервис для загрузки файла в мою серверную часть просто использует этот подход:

postImage(image: File): Observable<any> {
        const formData = new FormData()
        .append('file', image, image.name)
        }
        return this.httpClient.post<any>(this.myUrl,formData)
    }

И getImage из компонента myPage.ts, и postImage из uploadservice.ts работают нормально, но я не могу найти способ создать объект File из camera.getPicture imageData


person JoeCool    schedule 08.03.2018    source источник


Ответы (3)


Если вы не хотите использовать собственные плагины, вы всегда можете использовать angular. В этом случае используйте входной файл ion:

<ion-input type="file"></ion-input>

А остальное сделайте с помощью angular: https://www.academind.com/learn/angular/snippets/angular-image-upload-made-easy/

Вы можете использовать этот пример:

https://github.com/diegogplfree/Ionic3-fileupload-non-native

С уважением.

person Diego Arboleda    schedule 05.05.2018

Ответ в основном взят из здесь, но адаптирован для команды @ionic-native/camera plugin getPicture.

private urltoFile(url, filename, mimeType) {
    return (fetch(url)
        .then(function(res){return res.arrayBuffer();})
        .then(function(buf){return new File([buf], filename, {type:mimeType});})
    );
}

getPicture() {
    const options: CameraOptions = {
      quality: 50,
      destinationType: this.camera.DestinationType.DATA_URL,
      encodingType: this.camera.EncodingType.JPEG,
      mediaType: this.camera.MediaType.PICTURE,
      correctOrientation: true
    }

    this.camera.getPicture(options).then((imageData) => {

      let base64Image = 'data:image/jpeg;base64,' + imageData
      this.urltoFile(base64Image, 'filename.jpg', 'image/jpeg')
      .then((file) => {
          // You now have a file object that you can attach to a form e.g.
          this.myForm.get("imageToUpload").setValue(file)        
      })

    }, (err) => {
     // Handle error
    });
}

Ключевые моменты, на которые следует обратить внимание:

  1. Тип назначения должен быть DATA_URL
  2. Необходимо добавить data:image/jpeg;base64, к imageData
person mahi-man    schedule 15.10.2018
comment
Из документа ionic: DATA_URL может потреблять очень много памяти и вызывать сбои приложения или ошибки нехватки памяти. Если возможно, используйте FILE_URI или NATIVE_URI - person Clorichel; 13.02.2019

У меня была такая же проблема, и мне это понравилось, и это работает для меня. но следует отметить, что сначала я не показываю выбранное изображение. После загрузки видно только его.

openImage() {
const options: CameraOptions = {
  quality: 100,
  destinationType: this.camera.DestinationType.FILE_URI,
  sourceType: this.camera.PictureSourceType.PHOTOLIBRARY,
  correctOrientation: true,
  allowEdit: false
};

this.camera.getPicture(options).then(imageData => {
  this.ImageFile = imageData;
}, err => {
  this.commonProvider.showToast('Error occured while opening the image' + err);
});

}

upload(msg: string) {
this.businessProvider.upload(this.Id, this.ImageFile)
  .then(
    data => {
      let response = JSON.parse(data["response"]);
      if (response.code === '1') {
        this.commonProvider.showToast('Business successfully ' + msg);
        this.navCtrl.pop();
      } else {
        this.commonProvider.showToast(response.message);
      }
      this.commonProvider.dismissLoader();
    },
    error => {
      this.commonProvider.showToast(JSON.stringify(error));
      this.commonProvider.dismissLoader();
    }
  );

}

Это мой бизнес-провайдер

import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { ErrorObservable } from 'rxjs/observable/ErrorObservable';
import { catchError } from 'rxjs/operators';
import { Constant } from '../app/app.constants';
import { AuthenticationProvider } from '../providers/authentication';
import { FileTransfer, FileUploadOptions, FileTransferObject } from '@ionic-native/file-transfer';

@Injectable()
export class BusinessProvider {

  private actionUrl: string;

  constructor(
    private http: HttpClient,
    private auth: AuthenticationProvider,
    private constant: Constant,
    private transfer: FileTransfer
  ) {
    this.actionUrl = this.constant.getServerWithApiUrl() + 'Business/';
  }


  upload(Id: number, ImageFile): any {
    const fileTransfer: FileTransferObject = this.transfer.create();
    const headers = this.auth.getHeader();
    let options: FileUploadOptions = {
      fileKey: 'ionicfile',
      fileName: 'ionicfile.jpg',
      chunkedMode: false,
      mimeType: "image/jpeg",
      headers: { headers }
    }
    return fileTransfer.upload(ImageFile, this.actionUrl + 'Upload/' + Id, options);
  }

}

person Nifal Nizar    schedule 05.09.2018
comment
вы не предоставляете подробную информацию о своей функции businessProvider.upload (), поэтому мы не можем использовать ваше решение - person lucbonnin; 28.12.2018
comment
добавил недостающую часть - person Nifal Nizar; 29.01.2019
comment
не отвечая на вопрос, попросил решение БЕЗ fileTransfer - person Clorichel; 13.02.2019