Updating a User through the api in laravel - javascript

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

how can I upload a file using "react-query" and "type-script"?

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)

I am trying to send a post request with an authorization key as a parameter and keep receiving an error: "Program.user" must be a "User" instance

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)

Network Request Failed with FormData in React Native

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]}")
]
);
}

How to save files into AWS using signedURLs and ReactJS?

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 }
});
}
};

How to send POST request with files in react-native android

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

Categories