一、传统表单提交(同步上传)
先来复习一下 form 表单提交上传文件:
<div>
<form action="http://192.168.2.250/uppic" method = "post" encType = "multipart/form-data">
<input type = "file" name = "file"/>
<input type = "submit" />
</form>
</div>
上传文件时表单必须加:encType = "multipart/form-data"
。且提交方式也必须为
post 请求。enctype 属性规定在发送到服务器之前应该如何对表单数据进行编码。
默认地,表单数据会编码为 "application/x-www-form-urlencoded"。就是说,在发送到服务器之前,所有字符都会进行编码(空格转换为 "+" 加号,特殊符号转换为 ASCII HEX 值)。
encType = "multipart/form-data
这个方法提交的表单是同步的提交,因为提交完成还会进行页面跳转。体验不好故不用
根据提交返回的结果,查看提交的图片:
查看图片
其中
<input type = "file" name = "file" multiple/>
multiple 表示多文件上传
二、虚拟表单提交(异步上传)
因为传文件只能表单上传,不能简单的放个 input 就上传文件,所以异步就是通过创建虚拟表单来提交数据。
下面来进行创建:
<input type = "file" ref = "file" multiple/>
<button onClick = {()=>{
// 点击提交创建虚拟表单
let vform = new FormData();
console.log(this.refs.file.files)//这个是上传文件的对象
console.log(this.refs.file.files[0])
// 追加文件
vform.append('file',this.refs.file.files[0]);
axios.post("http://192.168.2.250/uppic",vform).then(data=>{
this.setState({
filename : data.data.filename
})
});
}}>提交</button>
{/*图片预览*/}
{
this.state.filename === "" ?
null : <img src = {`http://192.168.2.250/uploads/${this.state.filename}`} />
}
console.log(this.refs.file.files[0])打印出的单个信息文件。
单个文件详细信息
axios 进行 post 请求的时候,文件格式这样的:
axios.post('url, {
dataName: 'data'
})
也可以对第一个括号里面的数据进行整合下写成下面这样推荐使用:
axios({
method: 'post',
url: 'http://192.168.2.250/uppic',
data: vform,
onUploadProgress: function (progressEvent) {
// Do whatever you want with the native progress event
}
})
axios 上传进度条提示格式代码:
// `onUploadProgress` allows handling of progress events for uploads
onUploadProgress: function (progressEvent) {
// Do whatever you want with the native progress event
}
控制台打印出这个 progressEvent 形参,有两个很重要的参数,我们上传的进度就可以使用 loaded/total 来表示。
现在来完成异步上传组件:
import React, { Component } from 'react';
import { Progress } from 'antd';
import axios from "axios";
export default class S1 extends Component {
constructor(){
super();
this.state = {
filename : "",
progress : 0
}
}
render() {
return (
<div>
<input type = "file" ref = "file" multiple/>
<button onClick = {()=>{
// 点击提交创建虚拟表单
let vform = new FormData();
// 追加文件
vform.append('file',this.refs.file.files[0]);
axios({
method: 'post',
url: '/api/uppic',
data: vform,
onUploadProgress: (progressEvent)=> {
// ~~()取整
this.setState({
progress : ~~(progressEvent.loaded / progressEvent.total * 100)
})
}
}).then(data=>{
this.setState({
filename : data.data.filename
})
});
}}>提交</button>
{/*原型进度条*/}
<Progress type="circle" percent={this.state.progress} />
{/*上传完图片预览*/}
{
this.state.filename === "" ?
null : <img style = {{"width":"150px"}} src = {`http://192.168.2.250/uploads/${this.state.filename}`} />
}
</div>
)
}
}
把网速调慢实验效果如下:
是不很别扭,图片应该是上传前预览呀。
三、HTML5 把图片地址转成 base64
HTML5 把图片地址转成 base64,HTML5 新特性,用来做图片上传前的预览。
核心代码:
<input type = "file" ref = "file" multiple onChange = {(e)=>{
let file = e.target.files[0];
// HTML的新特性可以把图片变成base64地址
let fr = new FileReader();
fr.readAsDataURL(file);
fr.onload = (_e)=>{
this.setState({
base64 : _e.target.result
})
}
}}/>
上传前预览
完整代码示例:
import React, { Component } from 'react';
import { Progress , Icon} from 'antd';
import classnames from "classnames";
import axios from "axios";
export default class S1 extends Component {
constructor(){
super();
this.state = {
base64 : "",
progress : 0
}
}
render() {
return (
<div>
<input type = "file" ref = "file" multiple onChange = {(e)=>{
let file = e.target.files[0];
// HTML的新特性可以把图片变成base64地址
let fr = new FileReader();
fr.readAsDataURL(file);
fr.onload = (_e)=>{
this.setState({
base64 : _e.target.result
})
}
}}/>
<button onClick = {()=>{
// 点击提交创建虚拟表单
let vform = new FormData();
// 追加文件
vform.append('file',this.refs.file.files[0]);
axios({
method: 'post',
url: '/api/uppic',
data: vform,
onUploadProgress: (progressEvent)=> {
// ~~()取整
this.setState({
progress : ~~(progressEvent.loaded / progressEvent.total * 100)
})
}
}).then(data=>{
this.setState({
filename : data.data.filename
})
});
}}>提交</button>
<div className = "img">
{/*上传之前图片预览*/}
<div>
{
this.state.base64 === "" ?
null : <img style = {{"width":"150px"}} className = {classnames({
img1:this.state.progress > 0 && this.state.progress < 100
})} src = {this.state.base64} />
}
</div>
{/*原型进度条*/}
<div className = "img2">
<Progress className = {classnames({
isHidden:this.state.progress <= 0 || this.state.progress >= 100
})} type="circle" strokeColor = "primary" percent={this.state.progress} width = {150} />
</div>
</div>
</div>
)
}
}
网友评论