10

so currently I am trying to upload a file, and save it on the Google Clouds. But I am stuck at how to get the input file using React-Redux.

Basically, my back-end part already finish, I tested it using HTTPie with this command HTTP localhost:8000/v1/... @(file_path) and it works perfectly fine.

Now after I use input tag: <input type="file" onChange=""> I do not know how to get the file_path that are the user choose. And I dont even know whether I can get the uploaded file using this method.

Thank you

0

5 Answers 5

12

You cant handle onChange file by method <input type="file" onChange={this.handleChangeFile.bind(this)}>

handleChangeFile(event) { const file = event.target.files[0]; let formData = new FormData(); formData.append('file', file); //Make a request to server and send formData } 
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for the fast reply, Let me try !
Hi Bro, can you explain to me how to pass this data to the request ?
only way to upload a file to server is use FormData. in this case, you get a file from input and put that to FormData, then send a post request to server
cool bro, can you help me with my bigger problem. I already create the formData, but have a problem in the middle of sending the data. Please check my question here : stackoverflow.com/questions/46271093/…
2

First : Create a component file name 'FileUpload.js'

import React, { Fragment, useState, useEffect } from 'react' function FileUpload (props) { useEffect(() => { clearFileUpload() }, []) const [fileName, setFileName] = useState('') const [fileSize, setFileSize] = useState('') const [fileSizeKB, setFileSizeKB] = useState('') const [fileType, setFileType] = useState('') const [src, setSrc] = useState('') const clearFileUpload = () => { setFileName('') setFileSize('') setFileType('') setSrc('') props.dataChanger('') } const onPickFile = (e) => { e.preventDefault(); clearFileUpload() document.getElementById(props?.name).click() } const onFilePicked = (e) => { let files = e.target.files; let file_name = files[0].name; let file_size = getFileSize(files[0].size); let file_size_kb = getFileSizeKB(files[0].size); let file_type = getFileType(files[0]).toLowerCase(); setFileName(file_name) setFileSize(file_size) setFileSizeKB(file_size_kb) setFileType(file_type) if (props?.max_file_size_in_kb && file_size_kb > props?.max_file_size_in_kb) { alert('Maximum allowed file size = '+props?.max_file_size_in_kb+ ' kb') clearFileUpload() return false; } if (props?.allowed_extensions && !arrToLowerCase(props?.allowed_extensions).includes(file_type)) { clearFileUpload() alert('Allowed file type = '+props?.allowed_extensions) return false; } let fileReader = new FileReader(); fileReader.addEventListener('load', ()=>{ // console.log(fileReader.result); props.dataChanger(fileReader.result) setSrc(fileReader.result) }) fileReader.readAsDataURL(files[0]) } const getFileSize = (file_size) => { if ( (file_size/1024) >= 1024 ) { file_size= parseInt((file_size/1024)/1024) + ' MB'; } else{ file_size=parseInt(file_size/1024) + ' KB'; } return file_size; } const getFileSizeKB = (file_size) => { file_size=parseInt(file_size/1024); return file_size; } const getFileType = (file) => { return file?.type.split('/').pop(); } const arrToLowerCase = (arr=[]) => { return arr.map(str => str.toLowerCase()); } return ( <Fragment> <button className="btn btn-primary text-capitalize mr-2 mb-2" onClick={(e) => onPickFile(e)}>{props?.button_title || 'Upload File'}</button> {(props?.required && fileName?.length<=3 && !src ) ? <label className="label label-danger">Required</label> : ''} <br /> {fileName ? <label className="label label-primary">{fileName}</label> : ''} {fileSize ? <label className="label label-info">{fileSize}</label> : ''} <br /> {/* new upload file */} {(props?.type=='image' && src && (props?.prev_src)) ? <img src={src} style={{ maxHeight: "150px", maxWidth: "150px" }} alt="" className="mt-2" /> : ''} {/* previous image */} {(props?.type=='image' && (props?.prev_src) && !src) ? <img src={props?.prev_src} style={{ maxHeight: "150px", maxWidth: "150px" }} alt="" className="mt-2" /> : ''} {(props?.type=='image' && src && (props?.prev_src)) ? <button className="btn btn-danger btn-outline-danger pl-1 pr-0 py-0 ml-2" onClick={clearFileUpload} title="Remove file"><i className="icofont icofont-ui-close"></i></button> : ''} <input className='file d-none' type="file" data-show-upload="true" data-show-caption="true" id={props?.name} name={props?.name} required={props?.required ? true : false} onChange={(e) => onFilePicked(e)} /> </Fragment> ) } export default FileUpload 

Second : How to use this component in your form

 import FileUpload from './FileUpload.js' <FileUpload name="thumbImage" button_title="Thumbnail Image Upload" max_file_size_in_kb="200" dataChanger={(value) => dataChangerThumbnail(value)} type="image" prev_src={'localhost:8001/'+formData?.thumbImage} required allowed_extensions={[ 'jpg', 'jpeg', 'png', 'gif']} /> const dataChangerThumbnail = (value) => { setFormData({...formData, thumbImage: value}) } const formInitial = { thumbImage: '', } const [formData, setFormData] = useState(formInitial) 

Comments

0

Complete Example with AXIOS and FORMIK

import "./App.css"; import { useEffect, useState } from "react"; import * as Yup from "yup"; import { Formik, Field, Form, ErrorMessage, useField } from "formik"; import axios from "axios"; function App() { return ( <Formik initialValues={{ profile: [], }} validationSchema={Yup.object({ profile:Yup.array().min(1,"select at least 1 file") })} onSubmit={(values, props) => { let data = new FormData(); values.profile.forEach((photo, index) => { data.append(`photo${index}`, values.profile[index]); }); axios .post("you_api_for_file_upload", data, { headers: { "Content-Type": "multipart/form-data", }, }) .then((response) => { console.log(response); }) .catch((err) => { console.log(err); }); }} > {(formik) => { return ( <> <Form> <input id="file" name="profile" type="file" onChange={(event) => { const files = event.target.files; let myFiles =Array.from(files); formik.setFieldValue("profile", myFiles); }} multiple /> <ErrorMessage name="profile"/> <button type="submit" disabled={formik.isSubmitting}> Submit </button> </Form> </> ); }} </Formik> ); } export default App; 

Hope this will help you

Comments

0

I used Laravel and React and it worked for me

import { Avatar } from "@files-ui/react"; import PhotoCameraIcon from "@mui/icons-material/PhotoCamera const ProfileIndexPage = props => { const [imagenProfile, setImagenProfile] = React.useState(null); async function actualizarUsuario(usuarios) { const { id, username, email, password, Clave, Activo, avatar } = usuarios; const formData = new FormData(); formData.append("image", imagenProfile); formData.append("id", id); formData.append("name", isNotEmpty(username) ? username.toUpperCase() : ""); formData.append("email", isNotEmpty(email) ? email.toUpperCase() : ""); formData.append("password", password); formData.append("Activo", Activo); formData.append("avatar", avatar); await actualizar(formData).then(response => { toastSuccess(intl.formatMessage({ id: "SEGURIDAD.USUARIOS.CREAR_USUARIO.MESSAGES.EXITO.ACTUALIZAR" })); }).catch(err => { console.log('%c [test]-70', 'font-size:13px; background:pink; color:#bf2c9f;', err) }).finally(() => { setLoading(false); }); } const handleChangeSource = (selectedFile) => { props.setImagenProfile(selectedFile) }; return ( <> <ProfileCard perfil={perfil} setImagenProfile={setImagenProfile} imagenProfile={imagenProfile} dataFileBase64={dataFileBase64} /> <Avatar src={props.imagenProfile ? props.imagenProfile : `data:image/jpeg;base64,${props.dataFileBase64}`} alt="Avatar" onChange={handleChangeSource} /> </> ); } export default injectIntl(WithLoandingPanel(ProfileIndexPage));

The bakend

public function actualizar(Request $request) : JsonResponse { $request->validate([ 'image' => 'required|image|mimes:jpg,png,jpeg|max:3048' ]); $filePath = ""; //Validamos si existe if($request->hasFile('image')){ // 1. possibility Storage::delete($request->avatar); $file = $request->file('image'); $ext = $file->getClientOriginalExtension(); $filename = time().'.'.$ext; $filePath = $file->storeAs('avatar',$filename); } } 

Route::post('/usuario/actualizar', [UserController::class, 'actualizar']);

Comments

-1

Checkout this blog, very well explained upload feature in react with example. Below is upload code from above blog:

handleUploadedFiles = files => { var reader = new FileReader(); reader.onload = (e) => { //Split csv file data by new line so that we can skip first row which is header let jsonData = reader.result.split('\n'); let data = []; jsonData.forEach((element, index) => { if(index) { //Split csv file data by comma so that we will have column data const elementRaw = element.split(','); console.log(element, index); if(element) { let param = { 'id' : elementRaw[0], 'name' : elementRaw[1], 'age' : elementRaw[2], 'address' : elementRaw[3] } data.push(param); } } }); } console.log("TCL: Dashboard -> reader.readyState", reader.readyState) reader.readAsText(files[0]); } 

Comments