摘要:前言本期的主題是在中如何實(shí)現(xiàn)文件上傳。文件上傳解決方案目前比較主流的解決方案就是表單或者和表單來(lái)實(shí)現(xiàn)。文件上傳解決方案表單利用表單組件進(jìn)行文件上傳是遠(yuǎn)古時(shí)期就一直在用的方法而且還真經(jīng)久不衰,厲害了。
終于抽出時(shí)間來(lái)繼續(xù)更新自己的博客,最近忙得夠嗆...
對(duì)于該系列博客不知道大家有沒(méi)有這樣的看法,對(duì)于React常見(jiàn)的基礎(chǔ)東西并沒(méi)有過(guò)多或者詳細(xì)列出,感覺(jué)有點(diǎn)不符合系列標(biāo)題。的確,筆者一開(kāi)始也想把React基礎(chǔ)從頭到尾列一邊,但是想想看沒(méi)這個(gè)必要,因?yàn)檫@種基礎(chǔ)教程在網(wǎng)上多如牛毛,再寫(xiě)豈不是重復(fù)造輪子,所以筆者就挑一些相對(duì)“偏僻”但是肯定會(huì)用到的東西拿出來(lái)分享。
本期的主題是在React中如何實(shí)現(xiàn)文件上傳。文件上傳這個(gè)功能在實(shí)際開(kāi)發(fā)過(guò)程中用的地方相對(duì)較多,當(dāng)然還有很多花里胡哨的解決方案,不過(guò)萬(wàn)變不離其宗再?gòu)?fù)雜的解決方案也離不開(kāi)最基礎(chǔ)的技術(shù),所以筆者將文件上傳這一塊詳細(xì)整理了一下并且做了demo供大家參考學(xué)習(xí)。
文件上傳解決方案目前比較主流的解決方案就是form表單、fetch(或者axios)和form表單+fetch來(lái)實(shí)現(xiàn)。對(duì)于第二位而言,筆者本著能用原生就用原生的原則就沒(méi)有使用axios模塊。那么下面就一一開(kāi)始分享。
文件上傳解決方案--form表單利用表單組件進(jìn)行文件上傳是遠(yuǎn)古時(shí)期就一直在用的方法而且還真經(jīng)久不衰,厲害了。利用form表單的enctype屬性可以把表單提交的對(duì)象設(shè)置為多媒體資源,然后通過(guò)inuput:file就可以實(shí)現(xiàn)文件上傳的功能,例子如下:
import React, {Component} from "react" class FormUploadOnly extends Component { render() { return () } } export default FormUploadOnly;
這個(gè)solution相對(duì)便捷有效而且還不用考慮跨域的問(wèn)題,畢竟我們上傳的文件終究還是要訪(fǎng)問(wèn)API接口;不過(guò)這種方法還有一個(gè)不方便的地方,就是form表單會(huì)默認(rèn)跳轉(zhuǎn)也就是會(huì)在瀏覽器訪(fǎng)問(wèn)你所提交文件的那個(gè)接口,這個(gè)行為處理起來(lái)很麻煩。這個(gè)問(wèn)題筆者推薦通過(guò)一個(gè)iframe來(lái)解決。
文件上傳解決方案--fetchFetch是瀏覽器的原生API,可以像Ajax那樣請(qǐng)求后臺(tái)接口。不過(guò)因?yàn)樗腔赑romise的,所以不支持Promise的瀏覽器則無(wú)法使用該方法。閑話(huà)不說(shuō),如何通過(guò)fetch來(lái)實(shí)現(xiàn)上傳?
import React, {Component} from "react"; class FetchUpload extends Component { constructor(props) { super(props); this.fileInput = React.createRef(); } upload = () => { const data = new FormData(); data.append("file", this.fileInput.current.files[0]); //相當(dāng)于 input:file 中的name屬性 fetch("http://127.0.0.1:3001/file/upload", { method: "POST", body: data }).then(response => console.log(response)) }; render() { return () } } export default FetchUpload;
這個(gè)方法比較投機(jī)取巧,就是將input:type中的數(shù)據(jù)append到FormData中,F(xiàn)ormData會(huì)將數(shù)據(jù)編譯成鍵值對(duì),這樣可以被fetch發(fā)送至后臺(tái)(不僅僅限于fetch,也可以是ajax或者axios等等)。不過(guò)這種方法有個(gè)致命的問(wèn)題,那就是會(huì)有跨域問(wèn)題。對(duì)于這個(gè)問(wèn)題,筆者會(huì)在博客末尾提供相關(guān)解決方案。
文件上傳解決方案--fetch+form這個(gè)方案看小標(biāo)題和前面的內(nèi)容,相信大家都能猜到是什么樣子了。下面直接上代碼:
import React, {Component} from "react" class FormUpload extends Component { submit = (e) => { e.preventDefault(); let formData = new FormData(e.target); fetch("http://127.0.0.1:3001/file/upload", { method: "POST", body: formData //自動(dòng)將input:file的name屬性與文件對(duì)象組合成鍵值對(duì) }).then(response => console.log(response)) }; render() { return () } } export default FormUpload;
總的來(lái)說(shuō),這個(gè)方法和第二中方法在原理上是相同的,只是獲取的文件數(shù)據(jù)不是直接從input:type中獲取的,而是從form的提交事件中獲取的,其他的沒(méi)什么變化,所以也會(huì)遇到跨域的問(wèn)題。
后臺(tái)組成該博客的demo后臺(tái)是express寫(xiě)的,所以不管是跨域管理還是接收并保存文件都是基于Node模塊。
跨域管理筆者常用的Node服務(wù)跨域解決方案是第三方庫(kù)cors。當(dāng)然cors除了是這個(gè)第三方庫(kù)的名字,也有比較重要的W3C標(biāo)準(zhǔn),它對(duì)解決瀏覽器跨域問(wèn)題起到重要的作用,不過(guò)該博文的重點(diǎn)不在這所以不作贅述,相關(guān)的使用方法都在文末的demo里,有興趣的朋友可以嘗試用用,真的很high!
接收并保存文件因?yàn)閑xpress自身的request對(duì)象不包含上傳過(guò)來(lái)的文件對(duì)象,所以必須要用到第三方庫(kù)multer。負(fù)責(zé)處理multipart/form-data 類(lèi)型的表單數(shù)據(jù)和保存相關(guān)資源的作用。
小提示
利用multer初始化一個(gè)upload中間件對(duì)象時(shí)候需要指定一個(gè)“標(biāo)志符”,比如:
let upload = multer({storage: storage}).single("file");
這里的標(biāo)識(shí)符是file,對(duì)應(yīng)前面代碼中的:
和
data.append("file", this.fileInput.current.files[0])
這是一個(gè)不算大的坑,所以大家使用時(shí)候多多關(guān)注。
最后筆者奉上準(zhǔn)備好的demo,有興趣的話(huà)可以download下來(lái)耍耍。當(dāng)然里面還包含了下一篇文件下載的代碼,大家可以也順帶看看。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/98769.html
摘要:本篇所說(shuō)的文件下載也是基于和或者都行。的返回值是一個(gè)有意思的對(duì)象,它包含了很多方法,其中一個(gè)方法就是。通過(guò)的響應(yīng)頭獲取到文件名。接下來(lái)就是對(duì)標(biāo)簽的一系列操作,然后模擬點(diǎn)擊事件觸發(fā)下載動(dòng)作。 距離上次博文更新已經(jīng)快一個(gè)月了,期間忙于各種事情無(wú)法脫身。今天難得閑暇 and then 就來(lái)更新啦...上篇中我們了解了下載React中如何實(shí)現(xiàn)文件的上傳,雖然不算什么高大上的技術(shù)但實(shí)際開(kāi)發(fā)的時(shí)候...
摘要:現(xiàn)在回過(guò)頭總結(jié),才又進(jìn)一步的揭開(kāi)了閉包的一層后臺(tái)管理系統(tǒng)解決方案前端掘金基于系列的后臺(tái)管理系統(tǒng)解決方案。什么是繼承大多數(shù)人使用繼承不外乎是為了獲得基于的單頁(yè)應(yīng)用項(xiàng)目模板前端掘金小貼士本項(xiàng)目已升級(jí)至。 關(guān)于js、jq零碎知識(shí)點(diǎn) - 掘金寫(xiě)在前面: 本文都是我目前學(xué)到的一些比較零碎的知識(shí)點(diǎn),也是相對(duì)偏一點(diǎn)的知識(shí),這是第二篇。前后可能沒(méi)有太大的相關(guān)性,需要的朋友可以過(guò)來(lái)參考下,喜歡的可以點(diǎn)個(gè)...
摘要:假如有這么一段句子這件衣服是人民幣如果我們想將一個(gè)數(shù)字以人民幣的形式寫(xiě)進(jìn)去的話(huà)可以這么做最終顯示結(jié)果是這件衣服是人民幣其實(shí)它做了兩件事一個(gè)是加符號(hào),另一個(gè)是加分隔符。同時(shí)表示人民幣,表示美元。 今天來(lái)介紹一個(gè)非常international的東西。 i18n國(guó)際化(internationalization)的簡(jiǎn)稱(chēng)。之所以叫i18n,是因?yàn)樽帜竔和n之間有18個(gè)字母,所以才叫i18n。不...
摘要:驗(yàn)證路由所謂的驗(yàn)證路由其實(shí)就是該路由的外層加了一層驗(yàn)證機(jī)制,有授權(quán)的用戶(hù)才能進(jìn)入,反之都無(wú)法進(jìn)入。一起學(xué)系列也隨著這篇的結(jié)束而告一段落了。大家一起加油最后再獻(xiàn)上和本篇博文有關(guān)的代碼鏈接和示例頁(yè)面 時(shí)隔那么久,博主終于從睡夢(mèng)中醒來(lái)開(kāi)始更新博客啦!為自己的勤勞歡呼...(pia pia pia打臉)!本次我們接著上一篇博客繼續(xù)聊React-Router4。上篇我們主要了解了React-Ro...
摘要:中的包中的包主要有三個(gè)和。的理念上面提到的理念是一切皆組件以下統(tǒng)一稱(chēng)組件。從這點(diǎn)來(lái)說(shuō)的確方便了不少,也迎合一切皆組件的理念。組件是中主要的組成單位,可以認(rèn)為是或的路由入口。將該標(biāo)示為嚴(yán)格匹配路由。的屬性追加一條。 2019年不知不覺(jué)已經(jīng)過(guò)去19天了,有沒(méi)有給自己做個(gè)總結(jié)?有沒(méi)有給明年做個(gè)計(jì)劃?當(dāng)然筆者已經(jīng)做好了明年的工作、學(xué)習(xí)計(jì)劃;同時(shí)也包括該系列博客剩下的博文計(jì)劃,目前還剩4篇:分別...
閱讀 2311·2021-11-23 09:51
閱讀 3748·2021-11-11 10:57
閱讀 1391·2021-10-09 09:43
閱讀 2481·2021-09-29 09:35
閱讀 2013·2019-08-30 15:54
閱讀 1788·2019-08-30 15:44
閱讀 3179·2019-08-30 13:20
閱讀 1687·2019-08-30 11:19