如何使用 React 上传文件?
How to upload files using React?
所以目前我正在尝试上传一个文件,并将其保存在 Google 云端。但是我对如何使用 React-Redux 获取输入文件感到困惑。
基本上,我的后端部分已经完成了,我通过这个命令使用 HTTPie 对其进行了测试
HTTP localhost:8000/v1/... @(file_path)
它工作得很好。
现在我使用输入标签后:
<input type="file" onChange="">
我不知道如何获得用户选择的 file_path 。
而且我也不知道用这个方法能不能得到上传的文件
谢谢
您无法通过方法<input type="file" onChange={this.handleChangeFile.bind(this)}>
处理onChange文件
handleChangeFile(event) {
const file = event.target.files[0];
let formData = new FormData();
formData.append('file', file);
//Make a request to server and send formData
}
签出 this 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]);
}
使用 AXIOS 和 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;
希望对您有所帮助
首先:创建组件文件名'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
第二:如何在你的表单中使用这个组件
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)
所以目前我正在尝试上传一个文件,并将其保存在 Google 云端。但是我对如何使用 React-Redux 获取输入文件感到困惑。
基本上,我的后端部分已经完成了,我通过这个命令使用 HTTPie 对其进行了测试
HTTP localhost:8000/v1/... @(file_path)
它工作得很好。
现在我使用输入标签后:
<input type="file" onChange="">
我不知道如何获得用户选择的 file_path 。
而且我也不知道用这个方法能不能得到上传的文件
谢谢
您无法通过方法<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
}
签出 this 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]);
}
使用 AXIOS 和 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;
希望对您有所帮助
首先:创建组件文件名'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
第二:如何在你的表单中使用这个组件
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)