Axios to django-backend post image fail

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

Leave a Reply

(*) Required, Your email will not be published