I'm trying to upload an image to NestJs backend(backend uses multer) from React Native Frontend(Redux), using axios but it doesn't work and there are no logs from backend. I have tried formData.append but the request doesn't seem to reach the backend at all.
I know it's a lot of code but I'm racing against a deadline. Please help
Image Picker (expo-image-picker)
const pickImage = async () => { try { let result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ImagePicker.MediaTypeOptions.Images, allowsEditing: true, quality: 1, }); if (!result.cancelled) { // console.log(result?.uri); setLocalImage(result?.uri); } else Alert.alert("Delete", "Are you sure you want to delete the image", [ { text: "Yes", onPress: () => setProfilePicture(null) }, { text: "No" }, ]); } catch (error) { console.log("error reading image", error); } };
handleSubmit Function (typescript)
async function handleSubmit() { // console.log(_id, localImage, token); let filename = localImage.split("/").pop(); let match = /\.(\w+)$/.exec(filename); let type = match ? `image/${match[1]}` : `image`; const ext = match?.[1]; let FData = new FormData(); FData.append("image", { name: new Date() +"_image", uri: localImage, type: "image/jpg", } as any); if (localImage && _id && token) { console.log("Details: ", _id, localImage, token); dispatch(updateImageAction(_id, localImage, token) as any); } else { return; } }
user.actions.tsx (Redux action)
export const updateImageAction = (_id: string, FData: any, token: string) => async (dispatch: Dispatch) => { try { dispatch({ type: UPDATE_IMAGE_REQUEST, }); const config = { headers: { Accept: "application/json","Content-Type": "multipart/form-data", authorization: `Bearer ${token}`, }, }; const { data } = await axios.post( routes.user.updateProfileImage + `${_id}`, FData, config ); dispatch({ type: UPDATE_IMAGE_SUCCESS, payload: data, }); } catch (error: any) { // console.log({ fromActionError: error }); dispatch({ type: UPDATE_IMAGE_FAIL, payload: error?.response && error.response?.data?.message ? error?.response?.data?.message : error?.message, }); } };
Backend Code (Controller)
@UseGuards(AccessTokenGuard, IsOwnerGuard) @UseInterceptors(FileInterceptor('image')) @Post('/profile-image-upload/:userid') async uploadProfileImage( @UploadedFile() file: Express.Multer.File, @Param('userid') userid: string, @Request() req, ) { console.log("Endpoint's been hit"); const user = req?.user?.payload?.data; console.log('Details from User Controller: ', userid, user, file); return handleResponse({ success: true, data: [await this.userService.uploadProfileImage(file, userid, user)], message: 'Profile image uploaded successfully', }); }
Backend Code (Service)
async uploadProfileImage( file: Express.Multer.File, userid: string, user: Partial<User>, ) { try { console.log('Details from User Service: ', userid, user, file); const userFromDb = await this.UserModel.findById(userid); if (userFromDb.email !== user.email) { throw new HttpException('You cannot update a profile that is not yours', 400, ); } //DELETE PROFILE IMAGE FROM S3 IF IT EXISTS if (userFromDb.profilePicKey) { console.log('key: ', userFromDb.profilePicKey); await this.s3Service.deleteFile(userFromDb?.profilePicKey); } const key = `${file.fieldname}${Date.now()}`; const imageUrl = await this.s3Service.uploadFile(file, key); const updatedUser = await this.UserModel.findByIdAndUpdate( { _id: userid }, { profilePic: imageUrl, profilePicKey: key, }, { new: true }, ); return { profilePic: updatedUser?.profilePic, _id: updatedUser?._id, }; } catch (error) { // console.log(error?.message); throw new HttpException( error?.message || 'An error occured. Unable to upload profile image', error?.status || 500, ); } }