angular - Ionic 4 kullanarak görüntüyü yakalama ve sunucuya yükleme
Günlerdir bir görüntü yakalamaya ve sunucuya yüklemeye çalışıyorum ama başarılı olamadım. İstemci tarafı için Ionic 4 kullanıyorum ve arka uç olarak Java kullanıyorum (arka ucumu REST'e açmak için Jersey kullandım).
Şimdi, sorun şu ki, resmi çektikten sonra yüklemeye çalıştığımda backend'imde sürekli null alıyorum.
İşte benim istemci tarafı kodum :
openCam(){
const options: CameraOptions = {
quality: 100,
destinationType: this.camera.DestinationType.FILE_URI,
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE,
correctOrientation: true,
cameraDirection: 1
}
this.camera.getPicture(options).then((imageData) => {
// imageData is either a base64 encoded string or a file URI
// If it's base64 (DATA_URL):
//alert(imageData)
this.imageData = imageData;
this.image=(<any>window).Ionic.WebView.convertFileSrc(imageData);
this.isImageCaptureed = true;
}, (err) => {
// Handle error
alert("error "+JSON.stringify(err))
});
}
upload(){
let url = 'http://mydommain/api/upload';
let dataURL = 'data:image/jpeg;base64,' + this.imageData;
let postData = new FormData();
postData.append('file', dataURL);
let data:Observable<any> = this.http.post(url,postData);
data.subscribe((result) => {
console.log(result);
});
}
imageData öğesini doğrudan FormData nesnesine aktarmayı denedim, ayrıca başka benzer bir problemde bulduğum DataURIToBlob() fonksiyonunu kullanarak dönüştürmeyi de denedim ama yine de bir sonuç alamadım..
dataURItoBlob(dataURI) {
// convert base64/URLEncoded data component to raw binary data held in a string
var byteString;
if (dataURI.split(',')[0].indexOf('base64') >= 0)
byteString = atob(dataURI.split(',')[1]);
else
byteString = unescape(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
// write the bytes of the string to a typed array
var ia = new Uint8Array(byteString.length);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ia], {type:mimeString});
}
Sorunun sadece imageData formatında olduğunu biliyorum. HTML input etiketi kullanarak bir dosya seçmeyi başardım ve yukarıda bahsedilen aynı upload() fonksiyonunu ve backend API’mi kullanarak yükledim.
Cevap #1
İonic 4 ile çekilen görüntüleri arka uç sunucusuna yüklemenin ayrıntılı bir yolu burada.
Aşağıdaki CaptureImage sınıfına sahip olduğumuzu ve bu sınıfın çekilen görüntüyü yakalamaya ve yüklemeye adandığını varsayalım
export class CaptureImage implements OnInit {
constructor() { }
ngOnInit() {
}
}
Öncelikle, @ionic-native/camera öğesini şu şekilde yüklememiz gerekiyor :
ionic cordova plugin add cordova-plugin-camera
npm install @ionic-native/camera
Ionic Dokümantasyonuna başvurabilirsiniz
O zaman sınıfınıza bir kamera nesnesi tanımlamanız gerekir, böylece sınıfımız şöyle olacak:
import { Camera, CameraOptions } from '@ionic-native/camera/ngx';
export class CaptureImage implements OnInit {
//image to be displayed in template
image;
imageData;
constructor(private camera: Camera) { }
ngOnInit() {
}
}
Sonraki adımda, resmi yakalayacak bir fonksiyonu çağırmak için şablonumuzda bir tetikleyiciye ihtiyacımız var, bu nedenle şablon (capture-image.page.html) şöyle görünecek:
<ion-fab vertical="bottom" horizontal="end" slot="fixed">
<ion-fab-button (click)="capture()">
<ion-icon ios="ios-camera" md="md-camera"></ion-icon>
</ion-fab-button>
</ion-fab>
Bir capture() fonksiyonunu çağıran bir tıklama olayı tanımladığımızı unutmayın. Şimdi bu fonksiyonu uygulamamız gerekiyor.
O zaman CaptureImage sınıfımıza geri dönelim, işte capture() fonksiyonu:
openCamera(){
const options: CameraOptions = {
quality: 100,
destinationType: this.camera.DestinationType.DATA_URL,
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE,
}
this.camera.getPicture(options).then((imageData) => {
this.imageData = imageData;
this.image=(<any>window).Ionic.WebView.convertFileSrc(imageData);
}, (err) => {
// Handle error
alert("error "+JSON.stringify(err))
});
}
Lütfen hedefTipinin bu.camera.DestinationType.DATA_URL olması gerektiğini unutmayın
Tebrikler! Fotoğrafı çektiniz, çekilen fotoğrafı şablonunuzda şu şekilde görüntüleyebilirsiniz:
<img [src]="image" >
Şimdi bunu sunucuya yüklememiz gerekiyor. Basitlik açısından, yükleme fonksiyonunu doğrudan CaptureImage sınıfında uygulayacağım. Ancak gerçekte, tüm backend çağrılarını özel bir servis içinde uygulamak ve sonra bunu sınıfınıza enjekte etmek daha iyidir.
Yani resmi yüklemek için tekrar bir tetikleyiciye ihtiyacımız olacak, bu yüzden şablonumuzda bir yükleme butonu tanımlayalım :
<ion-button (click)="upload()" color="success">
<ion-icon slot="icon-only" name="checkmark"></ion-icon>
</ion-button>
O zaman CaptureImage sınıfına geri dönelim, önce HttpClient'i yapıcı metodda enjekte edelim
import { HttpClient } from '@angular/common/http';
export class CaptureImage implements OnInit {
//image to be displayed in template
image;
imageData;
constructor(private camera: Camera,
private http: HttpClient){ }
ngOnInit() {
}
}
o zaman, upload() fonksiyonunu tanımlayalım:
upload(){
let url = 'your REST API url';
const date = new Date().valueOf();
// Replace extension according to your media type
const imageName = date+ '.jpeg';
// call method that creates a blob from dataUri
const imageBlob = this.dataURItoBlob(this.imageData);
const imageFile = new File([imageBlob], imageName, { type: 'image/jpeg' })
let postData = new FormData();
postData.append('file', imageFile);
let data:Observable<any> = this.http.post(url,postData);
data.subscribe((result) => {
console.log(result);
});
}
Neredeyse bitti! Hâlâ bir fonksiyon daha uygulamamız gerekiyor: dataURItoBlob, bu fonksiyon dataURL'den blob dosyaları oluşturur:
dataURItoBlob(dataURI) {
const byteString = window.atob(dataURI);
const arrayBuffer = new ArrayBuffer(byteString.length);
const int8Array = new Uint8Array(arrayBuffer);
for (let i = 0; i < byteString.length; i++) {
int8Array[i] = byteString.charCodeAt(i);
}
const blob = new Blob([int8Array], { type: 'image/jpeg' });
return blob;
}
Son olarak, CaptureImage sınıfı sonunda bu şekilde görünecek :
import { Observable } from 'rxjs';
import { OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Camera, CameraOptions } from '@ionic-native/camera/ngx';
export class CaptureImage implements OnInit {
//image to be displayed in template
image;
imageData;
constructor(private camera: Camera,
private http: HttpClient) { }
ngOnInit() {
}
openCamera(){
const options: CameraOptions = {
quality: 100,
destinationType: this.camera.DestinationType.DATA_URL,
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE,
}
this.camera.getPicture(options).then((imageData) => {
this.imageData = imageData;
this.image=(<any>window).Ionic.WebView.convertFileSrc(imageData);
}, (err) => {
// Handle error
alert("error "+JSON.stringify(err))
});
}
upload(){
let url = 'your REST API url';
const date = new Date().valueOf();
// Replace extension according to your media type
const imageName = date+ '.jpeg';
// call method that creates a blob from dataUri
const imageBlob = this.dataURItoBlob(this.imageData);
const imageFile = new File([imageBlob], imageName, { type: 'image/jpeg' })
let postData = new FormData();
postData.append('file', imageFile);
let data:Observable<any> = this.http.post(url,postData);
data.subscribe((result) => {
console.log(result);
});
}
dataURItoBlob(dataURI) {
const byteString = window.atob(dataURI);
const arrayBuffer = new ArrayBuffer(byteString.length);
const int8Array = new Uint8Array(arrayBuffer);
for (let i = 0; i < byteString.length; i++) {
int8Array[i] = byteString.charCodeAt(i);
}
const blob = new Blob([int8Array], { type: 'image/jpeg' });
return blob;
}
}
Cevap #2
FormData Nesnesine atamadan önce Blob Veri'ye dönüştürmeyi deneyin.
const formData = new FormData();
const imgBlob = new Blob([reader.result], {
type: file.type
});
formData.append('file', imgBlob, file.name);
Referans Bağlantısı: https://devdactic.com/ionic-4-image-upload-storage/
