随着组件库越来越成熟,像图片上传这样的功能组件库已经封装好了不用再造轮子,但是在移动端,至少ant-desgn-mobile还没有集成图片上传的功能,所以还是需要我们自己手写,正好也再温习一下图片上传的写法。
首先页面需要一个type 是 file 的输入框,我的场景是只需要一个上传文件的按钮,所以没有采用表单提交的方式,而是直接走 fetch 上传。下面上代码
class Upload extends Component {
onChange = (e) => {
e.preventDefault();
const file = e.target.files[0];
const formData = new FormData();
// 这里的 image 是字段,根据具体需求更改
formData.append('image', file);
// 这里的 fetch 引用了 isomorphic-fetch 包
fetch('url', {
type: 'POST',
body: formData,
});
};
render() {
return {
<div className={styles['upload-container']}>
<input type="file" name="image" className={styles['upload-input']} onChange={this.onChange} />
<Button type="primary" className={styles['upload-button']}>上传图片</Button>
</div>
};
}
}
.upload-container {
position: relative;
}
.upload-input {
z-index: 200;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 47px;
display: inline-block;
opacity: 0;
}
.upload-button {
position: relative;
z-index: 100;
}
这样就实现了一个简单的文件上传功能,有两个需要注意的点:
第一点是页面布局,我的做法是将 input 框定位到 button 的上面,用户点击了按钮其实是点击了上传文件的input。
第二点是上传文件时,我们可以看到post请求的信息:
Content-type 是 multipart/form-data; boundary=----WebKitFormBoundary...,因为这里我们没有使用form的提交,所以也就没有设置 enctype 的地方。所以就干脆不要设置 Content-Type,这块一定要注意!
因为一般fetch我们都不是拿来直接用,需要进行一层封装,在封装的时候经常会默认设置一个 Content-Type,比如 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
,如果设置了这个 Content-Type 就没法上传文件了,然后我们可能覆盖默认设置 'Content-Type': 'multipart/form-data;
,本以为大功告成,但是设置以后发现Content-Type 被写死成 multipart/form-data;,后面的boundary=----WebKitFormBoundary...没有加上,这样还是无法上传。
所以做法就是不要设置 Content-Type ,这样就可以正常上传文件了。
上传文件的做法还有很多其他方式,比如 form 提交等等,这里只针对这个场景,其他方法以后遇到了我们再总结,如果你有其他很好的方法欢迎在下面评论分享!!!
最后科普点别的,GET 请求时默认会携带 cookie ,但是 POST 不会,在 fetch 需要设置 credentials: 'include',在请求时才会携带上cookie,credentials当然还有其他枚举值,详见:https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API/Using_Fetch#%E5%8F%91%E9%80%81%E5%B8%A6%E5%87%AD%E6%8D%AE%E7%9A%84%E8%AF%B7%E6%B1%82