隨著組件庫越來越成熟,像圖片上傳這樣的功能組件庫已經(jīng)封裝好了不用再造輪子,但是在移動端,至少ant-desgn-mobile還沒有集成圖片上傳的功能,所以還是需要我們自己手寫,正好也再溫習(xí)一下圖片上傳的寫法。
首先頁面需要一個type 是 file 的輸入框,我的場景是只需要一個上傳文件的按鈕,所以沒有采用表單提交的方式,而是直接走 fetch 上傳。下面上代碼
class Upload extends Component {
onChange = (e) => {
e.preventDefault();
const file = e.target.files[0];
const formData = new FormData();
// 這里的 image 是字段,根據(jù)具體需求更改
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;
}
這樣就實現(xiàn)了一個簡單的文件上傳功能,有兩個需要注意的點:
第一點是頁面布局,我的做法是將 input 框定位到 button 的上面,用戶點擊了按鈕其實是點擊了上傳文件的input。
第二點是上傳文件時,我們可以看到post請求的信息:

Content-type 是 multipart/form-data; boundary=----WebKitFormBoundary...,因為這里我們沒有使用form的提交,所以也就沒有設(shè)置 enctype 的地方。所以就干脆不要設(shè)置 Content-Type,這塊一定要注意!
因為一般fetch我們都不是拿來直接用,需要進行一層封裝,在封裝的時候經(jīng)常會默認設(shè)置一個 Content-Type,比如 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',如果設(shè)置了這個 Content-Type 就沒法上傳文件了,然后我們可能覆蓋默認設(shè)置 'Content-Type': 'multipart/form-data;,本以為大功告成,但是設(shè)置以后發(fā)現(xiàn)Content-Type 被寫死成 multipart/form-data;,后面的boundary=----WebKitFormBoundary...沒有加上,這樣還是無法上傳。
所以做法就是不要設(shè)置 Content-Type ,這樣就可以正常上傳文件了。
上傳文件的做法還有很多其他方式,比如 form 提交等等,這里只針對這個場景,其他方法以后遇到了我們再總結(jié),如果你有其他很好的方法歡迎在下面評論分享?。。?/p>
最后科普點別的,GET 請求時默認會攜帶 cookie ,但是 POST 不會,在 fetch 需要設(shè)置 credentials: 'include',在請求時才會攜帶上cookie,credentials當(dāng)然還有其他枚舉值,詳見: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