I try to upload some image from the camera gallery on localhost and prod environnement. My code works with a valid url like : https://res.cloudinary.com/dtdiwoz7o/image/upload/v1586706052/cn-2016-sashaonyshchenko-1920x1920-1510074905_dyfldk.jpg
But when I pass the image file path, it's return an 400 error.
Here is my code with some log :
_avatarClicked = () => {
const options = {
title: 'Select Photo',
storageOptions: {
skipBackup: true,
path: 'images',
},
};
ImagePicker.showImagePicker(options, (response) => {
if (response.didCancel) {
return
}
else if (response.error) {
return
}
else {
let data = {
file: response.uri,
upload_preset: "my_preset_name",
}
axios.post("https://api.cloudinary.com/v1_1/my_cloud_name/image/upload", data)
.then(res => console.log(res))
.catch(err => console.log(err))
}
})
}
log of my repsponse.uri :
(file:///Users/clement/Library/Developer/CoreSimulator/Devices/62E85527-A2AC-46CD-B517-E6039F99E056/data/Containers/Data/Application/E218E950-3A1C-40EB-8289-3837EC89FBBB/Documents/images/46674162-E32B-4302-B28A-5EF9150206D0.jpg)
I tried to replace in data file this by this 'const source' but it doesn't work :
const source = {
uri: response.uri,
type: response.type,
name: response.fileName,
}
I saw and test this on the react-native)image-picker documentation but I've got the same 400 error...
// const source = { uri: 'data:image/jpeg;base64,' + response.data };
I also try to Base64.encode(response.url) or Base64.encodeURI(response.url)
Please, can you help me ?
And sorry for my bad english
"react-native": "~0.61.4",
"react-native-image-picker": "^2.3.1",
///////////////////////////
I found the solution :
let data = {
file: 'data:image/jpg;base64,' + response.data,
upload_preset: "my_preset_name",
}
axios.post("https://api.cloudinary.com/v1_1/my_cloud_name/image/upload/", data)
.then(res => console.log(res))
.catch(err => console.log(err))
Ok I find the solution :
let data = {
file: 'data:image/jpg;base64,' + response.data,
upload_preset: "my_preset_name",
}
axios.post("https://api.cloudinary.com/v1_1/my_cloud_name/image/upload/", data)
.then(res => console.log(res))
.catch(err => console.log(err))
Related
While trying to upload a file I ran into an issue on iOS, the code works fine on android. After a bit of googling, I found that it is a known issue in react-native iOS and has a bug report submitted. This is the issue. I want to know if there is any other way to upload files on iOS. Below is the snippet of code I'm using. Please let me know if there is something that can be done.
const resp = await fetch(uploadUrl, {
method: 'POST',
headers: {
'content-type': 'multipart/form-data',
},
body: file, // file is File type
});
You can something like below code snippet
function uploadProfileImage(image, token) {
const url = ServiceUrls.UPLOAD_PROFILE_IMAGE
return uploadResourceWithPost({
url,
authToken: token,
formData: createFormData(image),
})
}
const createFormData = (data) => {
const form = new FormData()
form.append('file', {
uri: Platform.OS === 'android' ? data.uri : data.uri.replace('file://', ''),
type: 'image/jpeg',
name: 'image.jpg',
})
return form
}
const uploadResourceWithPost = ({ url, authToken, formData }) => {
return handleResponse(axios.post(url, formData, defaultUploadOptions(authToken)))
}
const defaultUploadOptions = (authToken) => ({
timeout,
headers: {
'X-Auth-Token': authToken,
'Content-Type': 'multipart/form-data',
},
})
const handleResponse = (responsePromise) => {
return NetInfo.fetch().then((state) => {
if (state.isConnected) {
return responsePromise
.then((response) => {
return ResponseService.parseSuccess(response)
})
.catch((error) => {
return ResponseService.parseError(error)
})
}
return {
ok: false,
message: 'Check your network connection and try again.',
status: 408,
}
})
}
const parseSuccess = ({ data, headers }) => ({ ...data, headers, ok: true })
const parseError = ({ response }) => {
let message = 'Check your network connection and try again.'
let status = 408
if (response && response.data) {
const { data } = response
message = data.message
status = data.code
}
return { status, message }
}
I am trying to download image which is coming from api.I am using rn-fetch-blob package to download file. But the problem here is when i click on download file do get downloaded but it gives some error saying
Download manager donwload failed , the file does not downloaded to destination
Any help would be great.
This is how i implemented rn-fetch-blob in my code
const checkPermission = async (image: string) => {
if (Platform.OS === 'android') {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
{
title: 'Storage Permission Required',
message: 'This app needs access to your storage to download Photos',
buttonPositive: 'OK',
},
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
console.log('Storage Permission Granted.');
handleDownload(image);
} else {
Alert.alert('Storage Permission Not Granted');
}
} catch (err) {
console.warn(err);
}
}
};
const getExtention = (filename: string) => {
//To get the file extension
return /[.]/.exec(filename) ? /[^.]+$/.exec(filename) : undefined;
};
// eslint-disable-next-line #typescript-eslint/no-unused-vars
const handleDownload = async (image: string) => {
let date = new Date();
let image_url = image;
let ext = getExtention(image_url);
const {config, fs} = RNFetchBlob;
let pictureDir = fs.dirs.PictureDir;
let options = {
fileCache: true,
addAndroidDownloads: {
useDownloadManager: true,
notification: true,
path:
pictureDir +
'/wallace_' +
Math.floor(date.getTime() + date.getSeconds() / 2) +
'.' +
ext,
description: 'Image',
},
};
config(options)
.fetch('GET', image_url)
.then((res) => {
console.log(res.path());
Alert.alert('Image Downloaded Successfully.');
})
.catch((err) => {
Alert.alert('Download Failed', err.message);
});
};
return <View>
<TouchableWithoutFeedback
onPress={() => handleShare(src.portrait)}>
<Text variant="buttonText">Share Image</Text>
</TouchableWithoutFeedback>
</View>
I trying to upload a file image to API in postman thats work fine but when a i try file image from ImagePicker didnot work.
I think doing something wrong when create formdata
Handler
ImagePicker.showImagePicker(optionsImagePicker, (response) => {
console.log('Response = ', response);
if (response.didCancel) {
console.log('User cancelled image picker');
} else if (response.error) {
console.log('ImagePicker Error: ', response.error);
} else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
} else {
// const source = { image: response.data };
let photo = { uri: response.uri}
let formdata = new FormData();
formdata.append("product[name]", 'test')
formdata.append("product[price]", 10)
formdata.append("product[category_ids][]", 2)
formdata.append("product[description]", '12dsadadsa')
formdata.append("product[images_attributes[0][file]]", {uri: photo.uri, name: 'image.jpg', type: 'image/jpeg'})
updateProfilePic(formdata)
// You can also display the image using data:
// const source = { uri: 'data:image/jpeg;base64,' + response.data };
// this.setState({
// avatarSource: source,
// });
}
});
Service
export function uploadImageProfile(data: any): Promise<any> {
const config = {
headers: {
'Content-Type': 'multipart/form-data',
},
};
return api.post('/users/profilepic', {image: data}, config).then((res) => {
console.log(res.data);
return res.data;
});
}
Your form data must be like that.
formdata.append('file',{
uri: Platform.OS === 'android' ? photo.uri : 'file://' + photo.uri,
name: 'test',
type: 'image/jpeg' // or your mime type what you want
});
Then
axios.post('/users/profilepic', formdata, config).then((res) => {
console.log(res.data);
return res.data;
});
let formdata = new FormData();
formdata.append('file',{
uri: Platform.OS === 'android' ? photo.uri : 'file://' + photo.uri,
name: 'test',
type: 'image/jpeg'
});
use method:"POST" and spread formdata.getHeaders() into header
let reqObj = {
method: "POST",
url: 'http://example.com/upload/image',
headers: {
'x-sh-auth': token,
...formdata.getHeaders()
},
maxContentLength: Infinity,
maxBodyLength: Infinity
};
axios(reqObj).then(result => {
console.log(result)
}).catch(error => {
console.log(error)
});
I changed how I send image to the server. Now send im base64 and in server convert to file with fs.
const uploadImage = {
imageBase64: 'data:' + response.type + ';base64,' + response.data,
};
updateProfilePic(uploadImage);
server side
async saveImageProfile(imageBase64, logedUserData) {
let base64Image = imageBase64.imageBase64.split(';base64,').pop();
let type = imageBase64.imageBase64.split('image/').pop().split(';')[0];
let newFileName = `${logedUserData.id}.${type}`;
if (imageFileFilter(type)) {
const file = await fs.writeFile('./files/' + newFileName, base64Image, { encoding: 'base64' }, function (err) {
console.log('File created');
});
const url = `${baseUrl}/users/files/${newFileName}`;
this.updateRefProfilePic(url, logedUserData);
}
else {
throw new BadRequestException("Tipo de arquivo não suportado");
}
}
I'm new in react native and this might be a silly question, but when I'm trying to upload .mp4 with react native using expo in my backend server side (laravel) I receive a jpg/jpeg file which is weird because with the same code when I try to upload .mov file it works as expected without any problem.
is there anything I've done wrong?
p.s: I've already tried to fetch method and axios but I get the same result with both.
here's my code:
postForm = () => {
var body = new FormData();
body.append("title", this.state.text);
body.append("description", this.state.description);
body.append("category_id", this.state.category_id);
body.append("type", this.state.type);
body.append('media_path', {
uri: this.state.photos.photos[0].file,
name: `media.mp4`,
type: this.state.format
});
this.state.photos.photos.map((item, index) => {
console.log("addable item is", index, item.file);
//skip first photo to media_path
if (index == 0) {
console.log("avalin index: ", item.file)
return
}
else {
file = item.file.toLowerCase();
console.log("full name is", file);
let addable = {
uri: item.file,
name: `addables`,
type: this.state.format
}
body.append("addables[]", addable)
}
})
console.log("final body: ", body);
this.setState({
uploading: true,
}, function () {
let apiUrl = `${config.BASE_URL}api/products`;
console.log(apiUrl);
axios({
method: 'POST',
url: apiUrl,
data: body,
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data',
"authorization": this.state.token
}
})
.then((response) => {
//handle success
console.log("success response: ", response);
if (response.data.status == true) {
this.setState({
uploading: false
}, function () {
this.props.navigation.push('profile');
})
}
else {
this.setState({
uploading: false
}, function () {
this.showToast("unsuccessful operation.", "danger", 3000);
})
}
})
.catch(function (response) {
//handle error
console.log(response);
alert("response)
});
})
}
and this is what laravel logs tels me:
array (
'title' => 'test',
'description' => 'test',
'category_id' => '3',
'type' => 'video',
'media_path' =>
Illuminate\Http\UploadedFile::__set_state(array(
'test' => false,
'originalName' => 'media.mp4',
'mimeType' => 'image/jpeg',
'error' => 0,
'hashName' => NULL,
)),
)
I am working on a mobile app using React Native and posting an image on iOS doesn't work. I have hooked up my code to requestbin, setup the info.plist to allow non-https urls and other post requests are working (e.g login). For the image, all I get is a blank body for the request. Here is the code posting the image:
uploadImage = () => {
const data = new FormData();
data.append('photo', {
uri: this.state.logo.uri,
name: 'logo'
});
fetch([requestbin url here], {
method: 'post',
body: data
}).then(res => {
console.log(res);
});
for the image, I am using react-native-image-picker to get it and store it in state under the variable 'logo'. Here is that code as well
handleNewImage = () => {
var options = {
title: 'Choose new company logo',
storageOptions: {
skipBackup: true,
path: 'images'
}
};
showImagePicker(options, response => {
console.log('Response = ', response);
if (response.didCancel) {
console.log('User cancelled image picker');
} else if (response.error) {
console.log('ImagePicker Error: ', response.error);
} else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
} else {
let source = { uri: response.uri };
// You can also display the image using data:
// let source = { uri: 'data:image/jpeg;base64,' + response.data };
this.setState({
logo: source
});
}
});
Remember that you also should pass a name key too, like below:
let url = "",
headers = "",
method = "POST",
body = new FormData(),
uri = "URI of the picked image.";
body.append("photo", {
name: "Just a name",
uri : Platform.OS === "android" ? uri : uri.replace("file://", "")
}
);
fetch(url, method, headers, body)
.then(function (response) {
})
.catch(function (error) {
});
function uploadProfilePicture(mImage) {
var data = new FormData();
data.append('theFile', { uri: mImage.uri, name: 'profile_photo.jpg', type: 'image/jpg' });
fetch(AppConstant.BASE_URL + AppConstant.upload_media, {
method: 'POST',
body: data
})
.then((response) => response.json())
.then((responseJson) => {
var err = 'error_message' in responseJson ? true : false
if (err) {
alert(responseJson.error_message)
} else {
alert(JSON.stringify(responseJson))
}
})
.catch((error) => {
console.error(error);
alert(error)
});
}
If anyone has issues with using fetch in iOS, check out react-native-file-upload I have found it to be extremely helpful in both image uploading and regular posts.