Issue
I’m using react frontend to communicate with Django backend through axios. For some reason, I can’t post form that include image. I tested my django backend through Postman and it works well.
The backend shows code 200 on the terminal as success without saving data and the frontend doesn’t through error
the form can post successfully if I excluded the image. Please check my code below ;
form.js file
import React, { useState } from 'react';
import { Helmet } from 'react-helmet';
import axios from 'axios';
import { connect } from 'react-redux';
import { setAlert } from '../actions/alert';
import './ApplicationForm.css';
import { useNavigate } from 'react-router-dom';
import ExpandLessIcon from '@mui/icons-material/ExpandLess';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import { IconButton } from '@mui/material';
function ApplicationForm({ setAlert }) {
const [show, setShow] = useState (false);
const navigate=useNavigate();
const [formData, setFormData] = useState({
pasport_number: '', first_name: '', last_name: '', passport_photo: ''
});
const { pasport_number, first_name, last_name, passport_photo } = formData;
const onChange = e => setFormData({ ...formData, [e.target.name]: e.target.value });
console.log (formData)
const onSubmit = e => {
e.preventDefault();
const config = {
headers: {
'Content-Type': 'application/json'
}
};
axios.post(`${process.env.REACT_APP_API_URL}/api/application-form/`, { pasport_number, first_name, last_name, passport_photo }, config)
.then(_res => {
navigate('/');
setAlert('Application Submitted Successfully', 'success');
})
.catch(_err => {
setAlert('Error with Sending Application', 'error');
})
};
return (
<div className='applicationForm'>
<div className='wrapper'>
<Helmet>
<title>Prosperity - Visa Application Form</title>
<meta
name='description'
content='Filling Application Form '
/>
</Helmet>
<div className='applicationForm__wrapper'>
<h1 className='applicationForm__title'>Application Form</h1>
<hr className='appform__hr'/>
<form className='applicationForm__form' onSubmit={e => onSubmit(e)}>
<div className='form__wrap'>
<hr className='appform__hr'/>
<p className='passport__section__title'>Enter or Import Passport Details</p>
<div className='input_grp'>
<div className='input_wrap input_wrap__bt'>
<p className='expand__p'>Enter Passport details</p>
<IconButton onClick={()=> setShow(true)}>
<ExpandMoreIcon className='Expand__bt'/>
</IconButton>
<IconButton onClick={()=> setShow(false)}>
<ExpandLessIcon className='Expand__less__bt'/>
</IconButton>
</div>
<div className='input_wrap input_wrap__bt import__passport'>
<label className='applicationForm__form__label' htmlFor='passport_photo'>Import Passport Image</label>
<input
className='input__for__two import__passport'
name='passport_photo'
type='file'
accept='image/*,.pdf'
placeholder='Import Passport'
onChange={e => onChange(e)}
value={passport_photo}
required
/>
</div>
</div>
{ show?
<>
<div className='input_grp'>
<div className='input_wrap'>
<label className='applicationForm__form__label appForm__subject' htmlFor='first_name'>First Name</label>
<input
className='applicationForm__form__input input__for__two'
name='first_name'
type='text'
placeholder='First Name *'
onChange={e => onChange(e)}
value={first_name}
required
/>
</div>
<div className='input_wrap'>
<label className='applicationForm__form__label' htmlFor='last_name'>Last Name</label>
<input
className='applicationForm__form__input input__for__two'
name='last_name'
type='text'
placeholder='Last Name *'
onChange={e => onChange(e)}
value={last_name}
required
/>
</div>
</div>
<div className='input_grp'>
<div className='form__wrap'>
<label className='applicationForm__form__label' htmlFor='pasport_number'>Passport Number</label>
<input
className='applicationForm__form__input input__for__two'
name='pasport_number'
type='text'
placeholder='Passport Number'
onChange={e => onChange(e)}
value={pasport_number}
required
/>
</div>
</div>
</>
:null
}
<hr className='appform__hr'/>
<button className='contact__form__button' htmltype='submit'>Send</button>
</div>
</form>
</div>
</div>
</div>
)
}
export default connect(null, { setAlert })(ApplicationForm);
console.log(formData) ;
{pasport_number: 'test3', first_name: 'test1', last_name: 'test2', passport_photo: 'C:\\fakepath\\signature.jpg'}
first_name: "test1"
last_name: "test2"
pasport_number: "test3"
passport_photo: "C:\\fakepath\\signature.jpg"
[[Prototype]]: Object
Updated form including react-file-base64 ;
import React, { useState } from 'react';
import { Helmet } from 'react-helmet';
import axios from 'axios';
import { connect } from 'react-redux';
import { setAlert } from '../actions/alert';
import './ApplicationForm.css';
import { useNavigate } from 'react-router-dom';
import ExpandLessIcon from '@mui/icons-material/ExpandLess';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import { IconButton } from '@mui/material';
import FileBase from "react-file-base64";
function ApplicationForm({ setAlert }) {
const [show, setShow] = useState (false);
const navigate=useNavigate();
const [formData, setFormData] = useState({
pasport_number: '', passport_photo: ''
});
const { pasport_number, passport_photo } = formData;
const onChange = e => setFormData({ ...formData, [e.target.name]: e.target.value });
console.log (formData);
const onSubmit = e => {
e.preventDefault();
const config = {
headers: {
'Content-Type': 'multipart/form-data',
'Accept': 'application/json'
}
};
axios.post(`${process.env.REACT_APP_API_URL}/api/application-form/`, { pasport_number, passport_photo }, config)
.then(_res => {
setAlert('Application Submitted Successfully', 'success');
})
.catch(_err => {
setAlert('Error with Sending Application', 'error');
})
};
return (
<div className='applicationForm'>
<div className='wrapper'>
<Helmet>
<title>Prosperity - Visa Application Form</title>
<meta
name='description'
content='Filling Application Form '
/>
</Helmet>
<div className='applicationForm__wrapper'>
<h1 className='applicationForm__title'>Application Form</h1>
<hr className='appform__hr'/>
<form className='applicationForm__form' onSubmit={e => onSubmit(e)} enctype="multipart/form-data">
<div className='form__wrap'>
<hr className='appform__hr'/>
<p className='passport__section__title'>Enter or Import Passport Details</p>
<div className='input_grp'>
<div className='input_wrap input_wrap__bt'>
<p className='expand__p'>Enter Passport details</p>
<IconButton onClick={()=> setShow(true)}>
<ExpandMoreIcon className='Expand__bt'/>
</IconButton>
<IconButton onClick={()=> setShow(false)}>
<ExpandLessIcon className='Expand__less__bt'/>
</IconButton>
</div>
<FileBase
type="file"
multiple={false}
onDone={({ base64 }) =>
setFormData({ ...formData, passport_photo: base64 })}
/>
</div>
{ show?
<>
<div className='input_grp'>
<div className='form__wrap'>
<label className='applicationForm__form__label' htmlFor='pasport_number'>Passport Number</label>
<input
className='applicationForm__form__input input__for__two'
name='pasport_number'
type='text'
placeholder='Passport Number'
onChange={e => onChange(e)}
value={pasport_number}
required
/>
</div>
</div>
</>
:null
}
<hr className='appform__hr'/>
<button className='contact__form__button' htmltype='submit'>Send</button>
</div>
</form>
</div>
</div>
</div>
)
}
export default connect(null, { setAlert })(ApplicationForm);
updated console.log ;
{pasport_number: 'TEST99', passport_photo: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAB4sA…LzzTqZ8wa/uf//J//+/8PoXjMydjnS20AAAAASUVORK5CYII='}
pasport_number: "TEST99"
passport_photo: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAB4s
[[Prototype]]: Object
django settings.py ;
from datetime import timedelta
import os
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
SECRET_KEY = 'xxx'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'accounts.apps.AccountsConfig',
'application_form.apps.ApplicationFormConfig',
'social.apps.SocialConfig',
'contacts.apps.ContactsConfig',
'rest_framework',
'djoser',
'corsheaders',
'rest_framework_simplejwt.token_blacklist'
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'pros.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'build')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'prosperity.wsgi.application'
# Database
# https://docs.djangoproject.com/en/4.0/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'prosdb',
'USER': 'postgres',
'PASSWORD': 'xxxxx',
'HOST': 'localhost'
}
}
# email addition
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.xxxx.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = '[email protected]'
EMAIL_HOST_PASSWORD = 'xxxxx'
EMAIL_USE_TLS = True
MAIL_FROM_ADDRESS='xxxxxx'
# Password validation
# https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/4.0/topics/i18n/
LANGUAGE_CODE = 'en-GB'
TIME_ZONE = 'CET'
DATE_INPUT_FORMATS = [
'%d-%m-%Y', '%Y-%m-%d',
'%m/%d/%Y', '%m/%d/%y',
'%b %d %Y', '%b %d, %Y',
'%d %b %Y', '%d %b, %Y',
'%B %d %Y', '%B %d, %Y',
'%d %B %Y', '%d %B, %Y',
]
USE_I18N = True
USE_TZ = True
DATA_UPLOAD_MAX_NUMBER_FIELDS = None
STATIC_URL = 'static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'build/static')
]
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated'
],
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
),
'DEFAULT_PARSER_CLASSES': [
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.MultiPartParser'
],
}
CORS_ORIGIN_ALLOW_ALL = True
FILE_UPLOAD_PERMISSIONS=0o640
# Token settings
SIMPLE_JWT = {
'AUTH_HEADER_TYPES': ('JWT',),
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=60),
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
'AUTH_TOKEN_CLASSES': (
'rest_framework_simplejwt.tokens.AccessToken',
)
}
DJOSER = {
'LOGIN_FIELD':'email',
'USER_CREATE_PASSWORD_RETYPE': True,
'USERNAME_CHANGED_EMAIL_CONFIRMATION': True,
'PASSWORD_CHANGED_EMAIL_CONFIRMATION': True,
'SEND_CONFIRMATION_EMAIL': True,
'SET_USERNAME_RETYPE': True,
'SET_PASSWORD_RETYPE': True,
'PASSWORD_RESET_CONFIRM_URL': 'password/reset/confirm/{uid}/{token}',
'USERNAME_RESET_CONFIRM_URL': 'email/reset/confirm/{uid}/{token}',
'ACTIVATION_URL': 'activate/{uid}/{token}',
'SEND_ACTIVATION_EMAIL': True,
'PASSWORD_RESET_CONFIRM_RETYPE': True,
'SERIALIZERS': {
'user_create': 'accounts.serializers.UserCreateSerializer',
'user': 'accounts.serializers.UserCreateSerializer',
'user_delete': 'djoser.serializers.UserDeleteSerializer',
}
}
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
AUTH_USER_MODEL = 'accounts.UserAccount'
Solution
This is a solution but there must be a better way to avoid creating another useState.
I created ; const [image, setImage] = useState(null);
then in the input; onChange{(e)=>setImage(e.target.files[0])}
I think there might be a way to use (e.target.files[0])) with passport_photo in my code and that will be awesome.
Answered By – Moammer
This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0