Reputation: 1092
I would like to upload an image to my back-end using FormData, but as Ionic DEVAPP and Ionic VIEW does not support file, file-transfer and file-upload plugins, I need to do it using only Angular Http or HttpClient.
When using DestinationType.FILE_URI, i can get the internal url from the file and display it on a img object, but I can't create a typescript File object from this url without the native file, file-path and file-transfer plugins.
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)
})
}
using this template
<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>
When using DestinationType.DATA_URL I can display the image but can not create the typescript File object needed with the original file name to append the image to the FormData used on my upload service at my Ionic App.
It seems I can find a way to create this typescript File object with the original filename from FILE_URI and a the base64 encoded data from DATA_URL using the camera.getPicture from the cordova camera native plugin.
Service to upload the file to my back-end just uses this approach:
postImage(image: File): Observable<any> {
const formData = new FormData()
.append('file', image, image.name)
}
return this.httpClient.post<any>(this.myUrl,formData)
}
Both getImage from component myPage.ts and postImage from uploadservice.ts work fine, but I can't find a way to create the File object from camera.getPicture imageData
Upvotes: 7
Views: 3850
Reputation: 82
If you don't want to use native plugins, you can always use angular. For this case use an ion input file:
<ion-input type="file"></ion-input>
And do the rest with angular: https://www.academind.com/learn/angular/snippets/angular-image-upload-made-easy/
You can use this example:
https://github.com/diegogplfree/Ionic3-fileupload-non-native
Upvotes: -2
Reputation: 963
I had the same issue and did like this and its works for me. but one thing to be note i'm not showing the selected image first. After uploading only its visible.
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();
}
);
}
This my business provider
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);
}
}
Upvotes: -1
Reputation: 4686
Answer mostly take from here but adapted for the @ionic-native/camera
plugin getPicture
command.
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
});
}
Key points to note are
DATA_URL
data:image/jpeg;base64,
to the imageData
Upvotes: -1