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
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 post an item to my server. I'm using React Native for my front end and Laravel as my back-end. I have tried it many times but it keeps giving me Network request failed. Though I am trying it on postman and it works fine.
This is my React-Native code::=>
const { name, price, category_id, description, images } = this.state
const formData = new FormData();
formData.append('name', name)
formData.append('price', price)
formData.append('category_id', category_id)
formData.append('description', description)
images.map((image) => {
var fileURI = image.uri;
let filename = fileURI.split('/').pop();
formData.append('images[]', { uri: fileURI, type: image.mime, name: filename });
})
//FETCH
const BASE_URL = BASE_URL
fetch(`http://192.168.8.102:8000/api/items`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data',
},
body: formData
}).then(response => {
const statusCode = response.status;
const responseJson = response.json();
return Promise.all([statusCode, responseJson]);
})
.then(res => {
const statusCode = res[0];
const responseJson = res[1];
if (statusCode == 200) {
console.log(responseJson)
Alert.alert(
'Post successfull🌟',
'Thank you for posting, there you go 🙌',
[
{ text: 'not now', style: 'cool', },
],
{ cancelable: true },
);
navigation.navigate('DrawerNavigation');
} else if (statusCode == 422) {
Alert.alert('invalid parameters', responseJson.message);
} else {
Alert.alert('account not created', 'something unexpected' + responseJson.message);
}
})
.catch(err => {
Alert.alert('server error', err.message);
}).finally(fin => this.setState({ loading: false }))
This is my Laravel code::=>
$images = $request->file(['images']);
$image_details = array();
foreach ($images as $image ) {
$path = $image->store('public/itemImages');
$exploded_string = explode("/",$path);
$image_details[] = new ItemImage (
[
'name' => $exploded_string[2],
'path' => "storage/{$exploded_string[1]}",
'url' => asset("storage/{$exploded_string[1]}/{$exploded_string[2]}")
]
);
}
I'm trying to attach images with regular text inputs into my form in order to submit to my MongoDB.
This is what my function to create a post looks like:
const [postData, setPostData] = useState({
text: '',
images: null,
postedto: auth && auth.user.data._id === userId ? null : userId
});
const { text, images, postedto } = postData;
const handleChange = name => e => {
setPostData({ ...postData, [name]: e.target.value, images: e.target.files });
};
const createPost = async e => {
e.preventDefault();
await addPost(postData, setUploadPercentage);
};
From there I move into my action addPost; on this function I call two API routes:
// #route POST api/v1/posts
// #description Add post
// #access Private
// #task DONE
export const addPost = (formData, setUploadPercentage) => async dispatch => {
try {
// ATTACH FILES
let fileKeys = [];
for(let file of formData.images) {
const uploadConfig = await axios.get(`${API}/api/v1/uploads/getS3url?type=${file.type}`);
await axios.put(uploadConfig.data.url, file, {
headers: {
'Content-Type': file.type
}
});
fileKeys.push(uploadConfig.data.key);
}
console.log(fileKeys);
// INSERT NEW BLOG
const config = {
headers: {
'Content-Type': 'multipart/form-data; application/json'
},
onUploadProgress: ProgressEvent => {
setUploadPercentage(
parseInt(Math.round(ProgressEvent.loaded * 100) / ProgressEvent.total)
);
// Clear percentage
setTimeout(() => setUploadPercentage(0), 10000);
}
};
formData.images = fileKeys;
const res = await axios.post(`${API}/api/v1/posts`, formData, config);
dispatch({
type: ADD_POST,
payload: res.data
});
dispatch(setAlert('Post Created', 'success'));
} catch (err) {
const errors = err.response && err.response.data.errors;
if (errors) {
errors.forEach(error => dispatch(setAlert(error.msg, 'danger')));
}
dispatch({
type: POST_ERROR,
payload: { msg: err.response && err.response.statusText, status: err.response && err.response.status }
});
}
};
My getS3url function looks exactly like this:
exports.uploadFile = asyncHandler(async (req, res, next) => {
const { type } = req.query;
const fileExtension = type.substring(type.indexOf('/') + 1);
const key = `${process.env.WEBSITE_NAME}-${req.user._id}-${
req.user.email
}-${Date.now().toString()}.${fileExtension}`;
const params = {
Bucket: process.env.AWS_BUCKET_NAME,
Key: key,
ContentType: type
};
s3.getSignedUrl(`putObject`, params, (err, url) => {
if (err) {
return next(
new ErrorResponse(
`There was an error with the files being uploaded`,
500
)
);
}
return res.status(201).json({ success: true, key: url });
});
});
I would like to point out that every post might have more than one image file and the function should return a signedURL for each single file; let's say I upload two files, I then should have two URLS retrieved in order to attach them into my post.
I'm sure there's nothing wrong with the way I;m managing state to submit data because it always return what I expect when using on console.log(postData) , even the files are shown.
Now I'm assuming the problem resides on my action, especially the code before the /// INSERT NEW BLOG comment because when I console.log(fileKeys) nothing is returned, not even an error/undefined/null.....I mean just nothing!.
My uploadFile is working fine when used with a single file....well not really because yes, it returns an URL of the 'supposed' uploaded file but when I get into my AWS console/bucket, there's nothing..but thats for its own post.
What I need help with?
Well, I'm trying to upload one/multiple files into my AWS using signedURL to return them as strings and attach them into my post. Is there any problem with my action file?.
Thanks!!.
for my case, I have been looping through the images and generating signed URLs and returning them since s3 doesn't support the signed URL option for multiple files at once.
In the end I found my own solution, here it is:
export const addPost = (formData, images, setUploadPercentage) => async dispatch => {
try {
let fileKeys = [];
for(let i = 0; i < images.length; i++) {
/// STEP 3
const token = localStorage.getItem("xAuthToken");
api.defaults.headers.common["Authorization"] = `Bearer ${token}`
const uploadConfig = await api.get(`/uploads/getS3url?name=${images[i].name}&type=${images[i].type}&size=${images[i].size}`);
// STEP 1
delete api.defaults.headers.common['Authorization'];
await api.put(uploadConfig.data.postURL, images[i], {
headers: {
'Content-Type': images[i].type
}
});
fileKeys.push(uploadConfig.data.getURL);
}
// INSERT NEW BLOG
const config = {
onUploadProgress: ProgressEvent => {
setUploadPercentage(
parseInt(Math.round(ProgressEvent.loaded * 100) / ProgressEvent.total)
);
setTimeout(() => setUploadPercentage(0), 10000);
}
};
// STEP 2
const token = localStorage.getItem("xAuthToken");
api.defaults.headers.common["Authorization"] = `Bearer ${token}`
const res = await api.post(`/posts`, {...formData, images: fileKeys}, config);
dispatch({
type: ADD_POST,
payload: res.data
});
dispatch(setAlert('Post Created', 'success'));
} catch (err) {
const errors = err.response && err.response.data.errors;
if (errors) {
errors.forEach(error => dispatch(setAlert(error.msg, 'danger')));
}
dispatch({
type: POST_ERROR,
payload: { msg: err.response && err.response.statusText, status: err.response && err.response.status }
});
}
};
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);
}