I'm trying to update user details through an api.
public function update(Request $request, $id)
{
$validator = Validator::make($request->all(), [
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'string|min:6|confirmed',
'phone' => 'string|min:6',
'Age' => 'string',
'Blood' => 'string',
'Gender' => 'string',
'Height' => 'string',
'Weight' => 'string',
'record' => 'string'
]);
if($validator->fails()){
return response()->json($validator->errors()->toJson(), 400);
}
$doc = User::find($id);
if($request->hasFile('picture')){
// Get filename with the extension
$filenameWithExt = $request->file('picture')->getClientOriginalName();
// Get just filename
$filename = pathinfo($filenameWithExt, PATHINFO_FILENAME);
// Get just ext
$extension = $request->file('picture')->getClientOriginalExtension();
// Filename to store
$fileNameToStore= $filename.'_'.time().'.'.$extension;
// Upload Image
$path = $request->file('picture')->storeAs('public/images', $fileNameToStore);
} else {
$fileNameToStore = 'noimage.jpg';
}
$doc->name = $request->input('name');
$doc->email = $request->input('email');
$doc->phone = $request->input('phone');
if($request->hasFile('picture')){
$doc->picture = $fileNameToStore;
}
$doc->save();
return response()->json([
'message' => 'Success',
]);
}
When I run this code, I get this
"{\"name\":[\"The name field is required.\"],\"email\":[\"The email field is required.\"]}"
I noticed that I get this error when I use form-data in post man, if I sent it raw instead, it works.
Then I tried to use it in my react native app, I get the same error as if I used form-data.
This is my code in react-native
const update = dispatch => {
return async (name, email, phone, picture, Age, Blood, Gender, Height, Weight, id) => {
const data = new FormData();
data.append('name', name);
data.append('email', email);
data.append('phone', phone);
data.append('Age', Age);
data.append('Blood', Blood);
data.append('Gender', Gender);
data.append('Height', Height);
data.append('Weight', Weight);
data.append("picture", {
type: 'image/jpg',
uri: picture,
name: 'profilepic.jpg'
});
const config = {
method: 'put',
url: `http://27a50145.ngrok.io/api/userregister/${id}`,
data: data,
headers: { 'Content-Type': 'application/json' }
}
await axios(config)
navigate('UserAccount')
}
}
Where in this codes is the error?
The way you need to change on Frontend.
Use Body instead of Data param.
const config = {
method: 'put',
url: `http://27a50145.ngrok.io/api/userregister/${id}`,
body: JSON.stringify(data),
headers: { 'Content-Type': 'application/json' }
}
Related
It's my API:
type UploadVideoParams = {
videofile: File
channelId: string | number
name: string
}
const uploadVideo = (
{ videofile, channelId, name }: UploadVideoParams,
onUploadProgress: (...args: any) => void
) => {
const formData = new FormData()
appendFormDataIfTruthy(formData, 'videofile', videofile)
appendFormDataIfTruthy(formData, 'channelId', channelId)
appendFormDataIfTruthy(formData, 'name', name)
const source = CancelToken.source()
return [
axiosInstance({
url: '/videos/upload',
method: 'POST',
headers: { 'Content-Type': 'multipart/form-data' },
data: formData,
onUploadProgress,
cancelToken: source.token,
}).then(res => res.data),
(msg: string) => {
source.cancel(msg)
},
]
}
How can I implement a react query hook for this API? We use typescript, react v17 and react-query v3.18.1.
I add this mutation but get this error in API:
export const useUploadMutation = () =>
useMutation(
VideosService.uploadVideo.name,
VideosService.uploadVideo as unknown as MutationFunction<unknown, UploadVideoParams>,
{
onSuccess: () => {
queryClient.invalidateQueries([VideosService.getVideos.name])
queryClient.invalidateQueries([VideosService.getChannelVideos.name])
},
}
)
but my API has this Error:
const cancelUpload: any Type 'void | [Promise, (msg: string) =>
void]' must have a 'Symbol.iterator' method that returns an
iterator.ts(2488)
The error I keep receiving is: ValueError: Cannot assign "<django.contrib.auth.models.AnonymousUser object at 0x102704820>": "Program.user" must be a "User" instance.
I am using Redux and making the post request using an action called createProgram which looks like this
export const createProgram = () => async (dispatch, getState) => {
try{
dispatch({ type: PROGRAM_CREATE_REQUEST})
const {
userLogin: { userInfo },
} = getState()
const config = {
header: {
'Content-type': 'application/json',
Authorization: `Bearer ${userInfo.token}`
}
}
const { data } = await axios.post(
`/api/programs/program-create/`,
{},
config
)
dispatch({
type: PROGRAM_CREATE_SUCCESS,
payload: data,
})
} catch (error) {
dispatch({
type: PROGRAM_CREATE_FAIL,
payload: error.response && error.response.data.detail
? error.response.data.detail
: error.message
})
}
}
I am using Dango for the backend and the createProgram view and model look as such:
#api_view(['POST'])
def createProgram(request):
user = request.user
program = Program.objects.create(
user = user,
name = 'Empty Name'
)
serializer = ProgramSerializer(program, many=False)
return Response(serializer.data)
class Program(models.Model):
user = models.ForeignKey(User, on_delete=CASCADE, null=False)
name = models.CharField(max_length=200)
dateCreated = models.DateTimeField(auto_now_add=True)
# lastWorkout = models.DateTimeField(auto_now_add=False) #I have to fix this
def __str__(self):
return str(self.name) + ' - ' + str(self.user.first_name)
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'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