前端本地图片上传总结
前言: 对于ant-Design或者element-UI这样的组件库,都帮助我们封装了 Upload 组件来帮助我们更好地实现文件上传的功能。这两家组件库都有action参数来帮助我们实现文件的自动上传,但是后端如果并没有提供action上传的地址,只能通过表单统一进行发送的时候我们又应该在怎么办呢?
ant-Design / element-ui 实现本地文件上传
这里仅讨论在antd和element-ui中,当我们并没有action上传地址,后端仅提供一个表单提交接口来完成所有表单项的提交任务的情况。
两种组件库都可以通过组件库自带的beforeUpload方法来获取上传的文件和阻止默认上传行为。对于element-ui可以设置auto-upload="false"来取消默认的上传行为。
以下代码通过onChange事件来获取上传的文件。
// ant-design
const Uploader = () => {
const [fileList, updateFileList] = useState([]);
const props = {
fileList,
beforeUpload: file => {
return false;
},
onChange: info => {
console.log(info.fileList);
// 当 beforeUpload return false时 file.status 为空
updateFileList(info.fileList.filter(file => !!file.status));
},
};
return (
<Upload {...props}>
<Button icon={<UploadOutlined />}>点击上传</Button>
</Upload>
);
};
// element-ui
// action如果没有最好写个空值,要不然控制台会报错。这里用before-upload方法也可以
<el-upload
action=""
:auto-upload="false"
:on-change="handleChange"
>
<el-button size="small" type="primary">选取文件</el-button>
</el-upload>
<script>
export default {
data() {
return {
fileList: []
};
},
methods: {
handleChange(file, fileList) {
this.fileList = [...fileList];
}
}
}
</script>
HTML + JS 实现本地文件上传
当项目中没有组件库或者组件库的样式并不满足我们的要求时,此时可以通过<input /> 标签进行文件上传。
使用 <input />
-
type属性,设置为file,使用户可以进行文件操作。
-
accept属性,通过接收设定文件的MIME类型来指定规定的文件格式。
-
multiple="multiple",可以设置是否可选多个文件。
<input type="file" name="myfile" />
修改样式
由于input自身的样式大多数不符合我们实际开发中的页面样式,因此我们可以隐藏input标签,通过另一个元素来调整页面上传组件的样式。
示例代码:
<div class="upload-btn" onclick="handleUpload()">点击上传</div>
<input type="file" style="display: none;" onchange="handleChange(this)">
<script>
let fileInput = document.getElementsByTagName('input')[0];
function handleUpload() {
fileInput.click();
}
function handleChange(target) {
console.log(target.files[0])
}
</script>
如果在使用react或者vue这类前端框架的时候,可以给input标签设置ref去控制input的点击效果。
// react
const Upload = () => {
const [fileList, updateFileList] = useState([]);
const ref = useRef(null);
const handleChange = (e) => {
console.log(e.target.files);
updateFileList(e.target.files);
}
const handleClick = () => {
const input = ref.current as HTMLInputElement;
if (input) {
input.click();
}
}
return (
<div onClick={handleClick}>
<input ref={ref} type="file" style={{display: 'none'}} onChange={handleChange} />
点击上传
</div>
);
}
<!-- vue -->
<div @click="clickUpload">点击上传</div>
<input
ref="fileInput"
type="file"
@change="handleChange"
style="display: none"
>
<script>
export default {
data() {
return {
fileList: []
};
},
methods: {
handleChange(e) {
console.log(e.target.files[0]);
this.fileList = [...e.target.files[0]];
},
clickUpload() {
this.$refs.fileInput.click();
}
}
}
</script>
数据提交
当完成了页面相关数据的采集之后,需要将获取到的数据传递给后端以结束这一系列操作。由于普通的json参数并不能满足传输File文件对象的需求,因此这里使用FormData,通过生成表单数据传递给后端。
let formData = new FormData();
formData.append('file', fileList); // fileList为组件中获取到的File对象
axios.xxx('url', formData); // 发送请求

浙公网安备 33010602011771号