I have been trying to send an image via native http POST request in my IONIC 4 app. I am getting the selected image and blob but when I am trying to append the same to my formData, my formData is always empty.
Here is my ts code
takePicture(sourceType: PictureSourceType) {
var options: CameraOptions = {
quality: 100,
sourceType: sourceType,
saveToPhotoAlbum: false,
correctOrientation: true
};
this.camera.getPicture(options).then(imagePath => {
if (this.platform.is('android') && sourceType === this.camera.PictureSourceType.PHOTOLIBRARY) {
this.file.resolveLocalFilesystemUrl(imagePath).then((entry: FileEntry) => {
entry.file(file => {
console.log(file);
this.readFile(file);
});
});
}
});
}
readFile(file: any) {
const reader = new FileReader();
reader.onloadend = () => {
const imgBlob = new Blob([reader.result], {
type: file.type
});
const formData = new FormData();
formData.append('file', imgBlob, file.name);
console.log(formData)
console.log(imgBlob)
this.uploadImageData(formData)
};
reader.readAsArrayBuffer(file);
}
async uploadImageData(formData) {
let feedbackData = {
attachment: formData,
feedback: 'test text'
}
this.http.post('http://abctest.rapidesk.in/api/feedback/', feedbackData, { 'Content-Type': 'multipart/form-data', 'Authorization': "Token" + " " + this.authToken })
.then(data => {
console.log(data);
}).catch(err => {
console.log(err)
})
}
I have shared the image of my console.
First console shows my image location and data
Second console is my formData
Third console is my imgBlob
You don't need to bind the image data to FormData. Please follow my code. This works fine with me. It may help you.
getFileFromCamera() {
this.translate.get(["FILE_ADDED_SUCCESSFULLY", "UNABLE_TO_TAKE_PHOTO"]).subscribe(
(values) => {
this.camera.getPicture({
destinationType: this.camera.DestinationType.DATA_URL,
targetWidth: 500,
targetHeight: 500,
quality: 100,
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE,
correctOrientation: true
}).then((data) => {
const imageData = 'data:image/jpg;base64,' + data;
this.AddDocumentForm.patchValue({'form_file': imageData}); // I am using reactive form group but you can directly add to the API body.
}, (err) => {
console.log(err);
this.csp.showToastMessage(2, values.UNABLE_TO_TAKE_PHOTO);
})
});
}
saveImage() {
this.api.post(endPoint, {image : this.AddDocumentForm.value.form_file).subscribe(()=>{
console.log(res);
});
}
// API service
post(endpoint: string, body: any, reqOpts?: any) {
return this.http.post(this.url + '?' + endpoint, body, reqOpts);
}
Related
I upload image with react js like this :
const onSubmit = (e) => {
console.log(e.img);
form.append("file", e.img.originFileObj);
Axios.post("url", form, {
headers: {
Authorization: `bearer ${localStorage.getItem("token")}`,
},
})
};
and the console log for the e.img is :
Now in react native I use the package react-native-image-crop-picker .
and after I set the image file it gives out an object like this :
{"cropRect": {"height": 960, "width": 960, "x": 0, "y": 160}, "height": 400, "mime": "image/jpeg", "modificationDate": "1636923018000", "path": "file:///storage/emulated/0/Android/data/com.myapp/files/Pictures/33fc6a3f-3673-4756-8343-6f6bcb3c1a7b.jpg", "size": 89454, "width": 400}
Now When I try to upload the image it gives error about the img file.
And the backend is node js and I handle image files with multer like this :
const multer = require('multer');
const uuid = require('uuid');
const MIME_TYPE_MAP = {
'image/png': 'png',
'image/jpeg': 'jpeg',
'image/jpg': 'jpg'
};
const fileUpload = multer({
limits: 20000000000,
storage: multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'upload/img');
},
filename: (req, file, cb) => {
const ext = MIME_TYPE_MAP[file.mimetype];
cb(null, uuid.v4() + '.' + ext);
}
}),
fileFilter: (req, file, cb) => {
const isValid = !!MIME_TYPE_MAP[file.mimetype];
let error = isValid ? null : new Error('Invalid mime type!');
cb(error, isValid);
}
});
module.exports = fileUpload;
How can I post the image file in react native like I do in react js ?
Solution 1
Like reactjs, here you can use FormData and append file in that like this:
asycn function uploadImage() {
const formData = new FormData();
const imageData = {
uri: cropImageData.path, // file uri/path
name: 'MyImage.jpg', //file name
type: cropImageData.mime, //file type
}
formData.append("file", imageData);
await fetch(url, {
method: "POST",
headers: {
'Content-Type': 'multipart/form-data',
Authorization: token,
},
data: formData,
}).then((response), {
console.log(response)
}).catch((error) => console.log(response));
}
Solution 2
or you can send base64 string from data, (you can get base64 from crop-image picker)
asycn function uploadImage() {
await fetch(url, {
method: "POST",
headers: {
'Content-Type': 'application/json',
Authorization: token,
},
data: JSON.stringify({
file: imageBase64String,
}),
}).then((response), {
console.log(response)
}).catch((error) => console.log(response));
}
here instead of fetch you can use axios too.
I solved the issue this way
ImagePicker.openPicker({
width: 400,
height: 400,
cropping: true,
includeBase64: true,
})
.then(image => {
setImg(image);
})
.then(() => setModalVisible(prev => !prev));
const nn = JSON.stringify(img.path).substring(
JSON.stringify(img.path).lastIndexOf('/') + 1,
);
const image = {
name: nn,
uri: img.path,
type: img.mime,
size: img.size,
lastModifiedDate: JSON.parse(img.modificationDate),
uid: img.modificationDate,
};
const form = new FormData();
form.append('file', image);
axios
.post('url', form, {
headers: {
Authorization: `bearer ${JSON.parse(token)}`,
},
})
I'm using react-native-image-crop-picker to get image from gallery and trying to upload it on the server using Axios.But its not uploading to the server and when I hit the api to upload it starts sending and never-ending and no response getting from server.But when I try to make its build and then try to upload then its uploaded successfully and gettting reponse from server.
Here is my code .
const handleProfilePic = () => {
const date = new Date();
const formData = new FormData();
formData.append('files', {
uri: image.path,
type: image.mime,
name: 'image_' + Math.floor(date.getTime() + date.getSeconds() / 2),
});
console.log(formData);
new Promise((rsl, rej) => {
setLoading(true);
updatePic(formData, user.auth, rsl, rej);
})
.then((res) => {
Snackbar.show({
text: res,
duration: Snackbar.LENGTH_SHORT,
});
setLoading(false);
})
.catch((errorData) => {
setLoading(false);
Snackbar.show({
text: errorData,
duration: Snackbar.LENGTH_SHORT,
});
});
};
//add pic code
export const updatePic = (data, token, rsl, rej) => {
return (dispatch) => {
axios(`${BASE_URL}/Authentication/addpicture`, {
method: 'post',
data,
headers: {
auth: token,
},
})
.then((res) => {
console.log(res);
if (res.data.status == true) {
rsl(res.data.message);
} else {
rej(res.data.message);
}
})
.catch((err) => {
console.log(err);
rej(err.message);
});
};
};
I've solved it by commenting this line
Open this dir 'android/app/src/debug/java/com/flatApp/ReactNativeFlipper.java'
NetworkingModule.setCustomClientBuilder(
new NetworkingModule.CustomClientBuilder() {
#Override
public void apply(OkHttpClient.Builder builder) {
// builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin));
}
});
I'm trying to send a file with rect-native 62.2 code with fetch request
when i select the file my fill array is this ->
{"data": ~blob image data~,"fileName": "Screenshot_20200504_082033.jpg", "fileSize": 347275, "height": 1544, "isVertical": true, "originalRotation": 0, "path": "/storage/emulated/0/DCIM/Screenshots/Screenshot_20200504_082033.jpg", "timestamp": "2020-05-04T02:50:33Z", "type": "image/jpeg", "uri": "content://media/external/images/media/126441", "width": 720}
i'm using the library for selecting the data is react-native-image-picker
the fetch request i'm sending is will look like this
var picForm = new FormData();
picForm.append('userId', userId);
picForm.append('file', source) // <- this is the main data
fetch(API_HOST + 'user/profilePictureUpload', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data',
Authorization: 'Basic jfjsfhsjkfhsjkjksksjjksfjkskfksdd',
Authorizationkeyfortoken:''fjsfsfjsfsjhfsjkfhjksfjksfjsf,
},
body: picForm,
}).then(res => res.text()).then(text => console.log(text)).catch(e => console.log(e));
for this code i'm getting an error source is [TypeError: Network request failed]
when i try this
var picForm = new FormData();
picForm.append('userId', userId);
picForm.append('file', {
uri: source.uri, //<- content://media/external/images/media/126441
type: 'image/jpeg',
name: source.fileName //<- Screenshot_20200504_082033.jpg
})
for this code i'm getting an error source is [TypeError: Network request failed]
var picForm = new FormData();
picForm.append('userId', userId);
picForm.append('file', source.files[0]) // <- this is the main data
the error appear is undefined object
var picForm = new FormData();
picForm.append('userId', userId);
picForm.append('file', 'files') // <- this is the main data
the network is correct but this is not i want to send this is the simple string do you guys any idea how to send the file with fetch request
please create image object like this way
var imageData = {
uri: iamge_path,
type: file_type, //the mime type of the file
name: file_name
}
const data = new FormData();
data.append("image",imageData)
Please make sure the request type is post, and your backend is handling the formdata correctly
This code working fine for me for multiple images upload , with photo description and user_id along with progress status
constructor() {
super();
this.state = {
uploadPercentage: 0,
}
}
// upload Files upload_Files = async () => {
upload_File() {
if (this.validate_Fields()) {
const { image, images, files, description, userId, size } = this.state;
console.log('AddPost Screen : upload_File:', 'userId:', userId, 'Files:', files, 'description:', description)
// this.setState({ error: '', loading: true });
if (this.state.type === 'image/jpeg') {
console.log('AddPost Screen : upload_ files :', files);
const formData = new FormData();
formData.append('user_id', userId);
formData.append('description', description);
// formData.append('files[]', files);
for (let i = 0; i < files.length; i++) {
formData.append('files[]', {
name: files[i].path.split('/').pop(),
type: files[i].mime,
uri: Platform.OS === 'android' ? files[i].path : files[i].path.replace('file://', ''),
});
}
// upload percentage progress bar ******************************************************
const options = {
onUploadProgress: (progressEvent) => {
const { loaded, total } = progressEvent;
let percent = Math.floor((loaded * 100) / total)
console.log(`${loaded}kb of ${total}kb | ${percent}%`);
if (percent < 100) {
this.setState({ uploadPercentage: percent })
}
}
}
axios.post(API_URL + '/fileuploadapi/uploadPost', formData, options, {
headers: { "Content-type": "multipart/form-data" }
}).then((response) => {
console.log(JSON.parse(JSON.stringify(response.status)));
// upload percentage progress
this.setState({ uploadPercentage: 100 }, () => {
setTimeout(() => {
this.setState({ uploadPercentage: 0 })
}, 1000);
})
this.cleanupImages();
Alert.alert('Upload Post Successfully');
}).catch((error) => {
console.log(error);
this.cleanupImages();
Alert.alert('image Upload Post Failed , Try again !');
});
}
}
}
// clear files data
cleanupImages() {
this.setState({
description: '',
image: null,
images: null,
// video: '',
files: '',
uploadPercentage: 0,
})
ImagePicker.clean().then(() => {
console.log('removed tmp images from tmp directory');
}).catch(error => {
alert(error);
});
}
If anything need let me know
i am new to ionic4/angular4.i need to upload the profile pic to database.i wrote code but i don't know whether it is correct or not and when i am uploading it i am getting the above mentioned error. backed i am using Django and sorry for the bad indentation.i just beginner to programming.
.ts
async sendPictureToSomewhere() {
const fileuri = await this.getPicture();
const blobinfo = await this.b64toBlob(fileuri);
await this.upload(blobinfo);
alert("done");
}
async getPicture() {
const options: CameraOptions = {
quality: 100,
destinationType: this.camera.DestinationType.FILE_URI,
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE
// targetWidth: 200
};
let fileuri = await this.camera.getPicture(options);
return fileuri;
}
b64toBlob(_imagePath) {
return new Promise((resolve, reject) => {
let fileName = "";
this.file
.resolveLocalFilesystemUrl(_imagePath)
.then(fileEntry => {
let { name, nativeURL } = fileEntry;
// get the path..
let path = nativeURL.substring(0, nativeURL.lastIndexOf("/"));
console.log("path", path);
console.log("fileName", name);
fileName = name;
// we are provided the name, so now read the file into
// a buffer
return this.file.readAsArrayBuffer(path, name);
})
.then(buffer => {
// get the buffer and make a blob to be saved
let imgBlob = new Blob([buffer], {
type: "image/jpeg"
});
console.log(imgBlob.type, imgBlob.size);
resolve({
fileName,
imgBlob
});
})
.catch(e => reject(e));
});
}
upload(_Blobinfo) {
this.profileService.postInfluencerProfile(_Blobinfo, null,
null).subscribe(
response => {
console.log(response);
},
(error: MavinError) => {
if (error instanceof NotFoundError) {
alert("Not found");
} else {
console.log(error);
}
}
);
}
}
Im wondering if there is a way to name the photos that I take with cordova camera, and if I can make like a search from the album, searching with the name, like photoName.jpg = mysearch
This is the service that I using to take the pictures.
var _takePhotoOff = function(url) {
return $q(function(resolve, reject) {
var options = {
quality: 50,
destinationType: Camera.DestinationType.FILE_URI,
sourceType: Camera.PictureSourceType.CAMERA,
allowEdit: true,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: true
};
$cordovaCamera.getPicture(options).then(function(imageData) {
var photo = {
url: url,
photo: imageData
}
resolve(photo);
});
});
}
You cannot specify the name of the image from the plugin, but you will find the image info including the file name in the imageData object, and using cordova-plugin-file plugin you can access and rename the file.
This is how I would do it
import { Injectable } from '#angular/core';
import { Camera } from '#ionic-native/camera';
import { FilePath } from '#ionic-native/file-path';
import { File } from '#ionic-native/file';
#Injectable()
export class CameraHandlerProvider {
constructor(private camera: Camera, private filePath: FilePath, private file: File ) {
}
config = {
quality: 100,
destinationType: this.camera.DestinationType.FILE_URI,
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE
}
getPic(fileName: string) {
this.camera.getPicture(this.config).then((imageData) => {
this.filePath.resolveNativePath(imageData)
.then((path) => {
console.log(imageData, path);
let imagePath = path.substr(0, path.lastIndexOf("/") + 1);
let imageName = path.substring(path.lastIndexOf("/") + 1, path.length);
this.file.moveFile(imagePath, imageName, this.file.dataDirectory, fileName)
.then(newFile => {
console.log(newFile);
})
.catch(err => {
console.error(err);
})
})
.catch((err) => {
console.error(err);
})
}).catch((err) => {
console.error(err);
});
}
}