Upload base64 image to the server with Axios and React native - asp.net

Actually we have site which use dropzone.js for uploading image to the server.
I'm working with react native app and need to replicate dropzone js behavior.
I'm trying to send base64 image but request return Multipart requests must contain at least one part.
saveImages(images) {
let config = {
headers: {
'Content-Type': 'multipart/form-data',
'X-Requested-With': 'XMLHttpRequest'
}
};
images.forEach(img => {
let imgFormData = `data:${img.mime};base64,${(img.data)}`;
let blob = this.dataURItoBlob(imgFormData);
let formData = new FormData(document.forms[0]);
formData.append('file', blob);
axios.post(SAVE_IMAGE_URL, formData, config)
.then(res => console.log(res))
.catch(err => {
console.log(err);
console.log(err.status);
console.log(err.code);
})
});
}
dataURItoBlob = (dataURI) => {
let byteString;
if (dataURI.split(',')[0].indexOf('base64') >= 0)
byteString = atob(dataURI.split(',')[1]);
else
byteString = unescape(dataURI.split(',')[1]);
let mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
let ia = new Uint8Array(byteString.length);
for (let i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ia], {type:mimeString});
}

Fixed with react-native-fetch-blob package
images.forEach(img => {
RNFetchBlob.fetch('POST', SAVE_IMAGE_URL, {
'Content-Type': 'multipart/form-data'
}, [
// element with property `filename` will be transformed into `file` in form data
{name: 'file', filename: 'file.png', data: img.data}
]).then((resp) => {
console.log(resp);
// ...
}).catch((err) => {
// ...
})
})

Related

Angular - Post request failing to download pdf file

I am trying to do a POST request to download a pdf file from the sever. The error I get is message: "Http failure during parsing". I'm not sure why it would work for a GET request but not for a POST request or I am missing something.
this.httpClient.post(url, {
responseType: 'blob' as 'json',
observe: 'response'
})
.pipe(take(1))
.subscribe((data:HttpResponse<Blob>) => {
const blob = new Blob([data.body], { type: 'application/pdf' });
saveAs(blob, 'test.pdf');
});
However if I do a GET request, it seems to work.
this.httpClient.get<Blob>(url,
{
observe: 'response',
responseType: (('blob') as any) as 'json'
})
.pipe(take(1))
.subscribe(
(response: HttpResponse<Blob>) => {
const blob = new Blob([response.body], { type: mediaType });
saveAs(blob, 'Report.pdf');
},
(error: any) => {
console.error(error);
}
);
Server
[HttpPost]
[Route("download/{id}")]
public IHttpActionResult DownloadPdf()
{
var buffer = _test.RenderDrawing();
var result = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ByteArrayContent(buffer)
};
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = $"Test.pdf"
};
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
return ResponseMessage(result);
}
In you post request, you are defining types differently. try something like this:
this.httpClient.post(url, {
responseType: 'blob',
observe: 'response'
})
.pipe(take(1))
.subscribe((data:HttpResponse<Blob>) => {
const blob = new Blob([data.body], { type: 'application/pdf' });
saveAs(blob, 'test.pdf');
});

NzUploadModule with AngularFireStorage

I'm trying to upload a file with AngularFireStorage service. File is uploaded and I can get download URL, but I can't pass status(progress,downloadurl) to nz-upload component. Is there someone solves it? I think S3 way may look like similar.
uploadFile = (item: UploadXHRArgs) => {
console.log('call uploadFile');
console.log(item);
const file = item.file;
const filePath = `${this.authService.user.uid}/${file.uid}`;
const fileRef = this.storage.ref(filePath);
const task = this.storage.upload(filePath, file)
return task.snapshotChanges().pipe(
finalize(() => {
fileRef.getDownloadURL().subscribe(result => {
console.log(result);
});
})
)
.subscribe();
}
handleChange({ file, fileList }: UploadChangeParam): void {
console.log(file.status);
const status = file.status;
if (status !== 'uploading') {
console.log(file, fileList);
}
if (status === 'done') {
this.msg.success(`${file.name} file uploaded successfully.`);
} else if (status === 'error') {
this.msg.error(`${file.name} file upload failed.`);
}
}
In browser console
call uploadFile
Object { action: "", name: "file", headers: undefined, file: File, postFile: File, data: undefined, withCredentials: false, onProgress: onProgress(e), onSuccess: onSuccess(ret, xhr), onError: onError(xhr)
}
uploading
https://firebasestorage.googleapis.com/v0/b/xxxx.appspot.com/o/bc7Q7zMxCWdJW0FtHrWtC0y6Vle2%2Fmnjvjqua0z?alt=media&token=6a50e16d-2b42-43b3-907a-add7f7a9b8f6
On a page
Solved, thanks to https://github.com/ezhuo/ngx-alain/blob/master/src/app/#core/utils/image.compress.service.ts#L123
uploadFile = (item: UploadXHRArgs) => {
const file = item.file;
const filePath = `${this.authService.user.uid}/${file.uid}`;
const fileRef = this.storage.ref(filePath);
const task = this.storage.upload(filePath, file);
return task.snapshotChanges().pipe(
finalize(() => {
fileRef.getDownloadURL().subscribe(result => {
item.onSuccess(result, item.file, result);
});
})
)
.subscribe(
(result) => {
const event = { percent: 0};
event.percent = (result.bytesTransferred / result.totalBytes) * 100;
item.onProgress(event, item.file);
},
err => {
item.onError(err, item.file);
}
);
}
P.S. Still trying to understand item.onSuccess(result, item.file, result); but upload and preview and progress, works.

How to Upload Image form Phone to Firebase Storage?

I'm trying to upload a Picture form my Phone to Firebase using Expo.
I get a uri form the Picture but not sure how to convert it, that I can uploade it to Firebase?
_pickImage = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
allowsEditing: true,
aspect: [4, 3],
});
if (!result.cancelled) {
console.log('device URL: w',result.uri);
this.setState({ image: result.uri });
this.uploadImage(result.uri).then(resp =>{
alert('success')
}).catch(err=>{
console.log(err)
})
}
};
When i Log result.uri I get:
file:///var/mobile/Containers/Data/Application/1E5612D6-ECDB-44F4-9839-3717146FBD3E/Library/Caches/ExponentExperienceData/%2540anonymous%252FexpoApp-87f4a5f5-b117-462a-b147-cab242b0a916/ImagePicker/45FA4A7B-C174-4BC9-B35A-A640049C2CCB.jpg
How can I convert it to a format that works for firebase?
you can convert the image to a base64, there are several libraries that can do that.
You need to convert the image to a base64, here is an example using rn-fetch-blob
https://github.com/joltup/rn-fetch-blob
export const picture = (uri, mime = 'application/octet-stream') => {
//const mime = 'image/jpg';
const { currentUser } = firebase.auth();
const Blob = RNFetchBlob.polyfill.Blob;
const fs = RNFetchBlob.fs;
window.XMLHttpRequest = RNFetchBlob.polyfill.XMLHttpRequest;
window.Blob = Blob;
return ((resolve, reject) => {
const uploadUri = Platform.OS === 'ios' ? uri.replace('file://', '') : uri;
let uploadBlob = null;
const imageRef = firebase.storage().ref('your_ref').child('child_ref');
fs.readFile(uploadUri, 'base64')
.then((data) => {
return Blob.build(data, { type: `${mime};BASE64` });
})
.then((blob) => {
uploadBlob = blob;
imageRef.put(blob._ref, blob, { contentType: mime });
})
.then(() => {
//take the downloadUrl in case you want to downlaod
imageRef.getDownloadURL().then(url => {
// do something
});
});
});
};

Observable from 2 promises

I think my solution is in this question but I can't get it to work Promise.all behavior with RxJS Observables?
I'm trying to return an observable on two promises via forkJoin.
One promise gets an ID from the server and another processes a file to generate a thumbnail.
export function createSceneFromFile(action$) {
return action$.ofType(CREATE_SCENE_FROM_FILE)
.mergeMap(({locationId,file}) =>
createSceneThumb(locationId,file)
.map((res,preview) => {
console.log(res,preview)
if (res.error) {
return { type: CREATE_SCENE_FAILED, payload: res.message }
} else {
return {type: CREATE_SCENE_SUCCESS, payload: {...res.payload,preview} }
}
})
.catch(err => { return { type: CREATE_SCENE_FAILED, message: err } })
)
}
function createSceneThumb(locationId,file){
const request = fetch(`${API_URL}/location/${locationId}/createscene/${file.name}/`, {
method: 'get',
credentials: 'include',
}).then(res => res.json())
const thumb = fileToScenePreview(file)
return Observable.forkJoin(request,thumb)
}
export function fileToScenePreview(file){
return new Promise((resolve,reject)=>{
getFileThumb(file).then((canvas)=> {
canvas.toBlob((blob) => {
blob.lastModifiedDate = new Date()
blob.name = 'scenepreview_' + file.name + '.png'
const uploader = new S3Upload({
getSignedUrl: getSignedUrl,
uploadRequestHeaders: {'x-amz-acl': 'public-read'},
contentType: 'image/png',
scrubFilename: (filename) => filename.replace(/[^\w\d_\-.]+/ig, ''),
contentDisposition: 'auto',
s3path: 'assets/',
onError:()=>reject,
onFinishS3Put: ()=>resolve(blob.name),
})
uploader.uploadFile(blob)
})
})
})
}
But i never get a response.
Is this the right way of going about it?

Ionic 3 File-Transport multipart/form-data

i am actually working on a mobile app in ionic v3 with angular5
The goal is to be able to take a picture or choose from existing ones and then upload it to the server. The first part is done, but i am struggling with the upload.
The api needs multipart/form-data which must consist of two requests. First with text part and second is the image.
Is there any solution for this?
This is what I have done for similar requirement
takePhoto() {
this.camera.getPicture({
quality: 100,
destinationType: this.camera.DestinationType.FILE_URI,
sourceType: this.camera.PictureSourceType.CAMERA,
encodingType: this.camera.EncodingType.PNG,
saveToPhotoAlbum: true
}).then(imageData => {
this.myPhoto = imageData;
this.uploadPhoto(imageData);
}, error => {
this.functions.showAlert("Error", JSON.stringify(error));
});
}
selectPhoto(): void {
this.camera.getPicture({
sourceType: this.camera.PictureSourceType.PHOTOLIBRARY,
destinationType: this.camera.DestinationType.FILE_URI,
quality: 100,
encodingType: this.camera.EncodingType.PNG,
}).then(imageData => {
this.myPhoto = imageData;
this.uploadPhoto(imageData);
}, error => {
this.functions.showAlert("Error", JSON.stringify(error));
});
}
private uploadPhoto(imageFileUri: any): void {
this.file.resolveLocalFilesystemUrl(imageFileUri)
.then(entry => (<FileEntry>entry).file(file => this.readFile(file)))
.catch(err => console.log(err));
}
private readFile(file: any) {
const reader = new FileReader();
reader.onloadend = () => {
const formData = new FormData();
const imgBlob = new Blob([reader.result], { type: file.type });
formData.append('evaluationID', this.currentEvaluation.evaluationId);
formData.append('standardID', this.currentEvaluation.id);
formData.append('score', this.currentEvaluation.score);
formData.append('comment', this.currentEvaluation.comment);
formData.append('file', imgBlob, file.name);
this.saveStandard(formData);
};
reader.readAsArrayBuffer(file);
}
And here is code for provider
saveStandard(receivedStandardInfo:any){
return new Promise((resolve, reject) => {
this.http.post(apiSaveStandard,receivedStandardInfo)
.subscribe(res => {
resolve(res);
}, (err) => {
console.log(err);
reject(err);
});
}).catch(error => { console.log('caught', error.message); });
}

Resources