Retrofit 實(shí)現(xiàn)文字(參數(shù))和多張圖片一起上傳

需求

Retrofit普及后,最近好多人都在問,如何實(shí)現(xiàn)Retrofit上傳多文件+文字需求(朋友圈發(fā)圖片+文字)

解決方案

google: retrofit upload multiple files

說重點(diǎn)

與其直接說答案,不如我們花點(diǎn)時(shí)間說說多文件上傳的原理辈挂,這樣,以后就算出了其他的http框架裹粤,你也能快速實(shí)現(xiàn)终蒂。

HTTP協(xié)議就不講了吧?反正copy一段過來也不會(huì)有人看遥诉。我們就直接跳到文件上傳去拇泣。想看也可以,傳送門

post form 表單

upload01.png

上圖是不是很常見矮锈,在網(wǎng)頁里選一個(gè)文件霉翔,點(diǎn)擊上傳。上傳到哪里苞笨?服務(wù)器咯债朵。web和移動(dòng)端本質(zhì)上有區(qū)別嘛?木有啊猫缭,就是一個(gè)前端展示的client葱弟。那服務(wù)器會(huì)為移動(dòng)端創(chuàng)造一套獨(dú)立的API嘛壹店?顯然他沒那么傻猜丹。

這個(gè)文件上傳經(jīng)常會(huì)伴隨著其他fields一起上傳」杪可以簡(jiǎn)單理解為表單上傳射窒。

先來看下藏杖,如果沒有文件,也不用json脉顿,單獨(dú)上傳一些key value怎么做蝌麸?在Postman里可以這樣模擬。

upload03.png

表單上傳要注意的是

  1. content-type設(shè)為application/x-www-form-urlencoded
  2. form表單在streaming時(shí)是"weibo=stay4it&wechat=stay4it&qq=104816053"

多文件上傳

實(shí)際上艾疟,多文件上傳與form表單是一回事来吩,一個(gè)key對(duì)應(yīng)一個(gè)value。文件上傳就是文件名key對(duì)應(yīng)文件byte[] value蔽莱,如下圖postman模擬請(qǐng)求

upload04.png

只是如何標(biāo)記一個(gè)key value的開始結(jié)束呢弟疆?用&分割肯定不夠用啦。那就得用個(gè)特殊的boudary來做為分隔符盗冷。

另外怠苔,這個(gè)content-type得為multiple/form-data

好了∫翘牵科普到此結(jié)束柑司。簡(jiǎn)單理解HTTP協(xié)議以及form表單概念,相信接下來的代碼你就不只是會(huì)調(diào)用锅劝,還能明白為什么攒驰。

最原始的上傳方式

以前大家都用HttpUrlConnection,Stay在自己動(dòng)手寫HTTP框架-19課時(shí)詳細(xì)講過如何上傳多文件以及進(jìn)度更新故爵。這里貼下核心代碼:

upload05.png

以上這個(gè)UploadUtil讼育,拿到outputstream,分別寫入postContent以及List<FileEntity>稠集,代碼不多奶段,相信大家都能看明白。

抓個(gè)包看看

請(qǐng)求數(shù)據(jù)抓包

upload06.png

上傳的有兩個(gè)form剥纷,
一個(gè)content-typetext/plain key為data, value為stay4it痹籍。
一個(gè)content-typeimage/png key為file0, value為文件的bytes

服務(wù)器如何接收的?(PHP版)

upload08.png

代碼還算好懂晦鞋,$_FILES就是請(qǐng)求上傳的多文件蹲缠,只要content-type設(shè)置為multiple/form-data,服務(wù)器接收是就會(huì)將其當(dāng)成文件處理悠垛,將文件接收在$_FILES中线定,等待處理(存數(shù)據(jù)庫,存硬盤或轉(zhuǎn)七牛云等等)确买,$this->data是表單中key為data所對(duì)應(yīng)的valuestay4it斤讥。(以后再有服務(wù)器er告訴你分兩個(gè)API上傳,你就可以這么懟他了: )

返回結(jié)果抓包

upload07.png

好了湾趾,原始的方式聊的差不多了芭商,雖然代碼看起來很多派草,但已經(jīng)是個(gè)util類了,倒不是那么難用铛楣。但是我們還是希望在寫代碼時(shí)能盡可能少的去關(guān)注內(nèi)部實(shí)現(xiàn)啊近迁。什么multiple/form-data,什么boundary簸州。真是很麻煩嘛鉴竭。

鳥槍換大炮吧

以下Retrofit多文件上傳內(nèi)容由一葉飄舟大神提供。

Retrofit實(shí)現(xiàn)文件和圖片一起上傳

如果對(duì)retrofit不是很了解岸浑,參考:初識(shí)Retrofit

定義接口

根據(jù)對(duì)Stay自己動(dòng)手寫HTTP框架-19課時(shí)提供的上傳圖片接口的大量抓包和測(cè)試總結(jié)拓瞪,接口定義如下:

upload09.png

這里用到了@Partmap注解,將圖片文件信息放入map中助琐。

準(zhǔn)備圖片

在sdcard根目錄存放兩張圖片祭埂,分別為test.png和test.jpg(不要是gif圖片啊,服務(wù)器不支持)

代碼實(shí)現(xiàn)

這里就不貼代碼了兵钮,截圖如下(如果看不清蛆橡,鼠標(biāo)右鍵在新窗口打開就可以看到原圖了):

upload10.png

關(guān)鍵代碼在于:

upload11.png

看到這個(gè)是不是想起了上面我們提到的關(guān)鍵代碼呢?下面再貼出來我們對(duì)比下掘譬。

upload12.png

只要將對(duì)應(yīng)的http請(qǐng)求頭信息填寫正確泰演,就能上傳成功。

那么問題又來了葱轩,怎么分析和正確拼寫這個(gè)請(qǐng)求頭呢睦焕?

在文章開頭的時(shí)候有個(gè)抓包信息:

Content-Disposition: form-data; name="file0"; filename="test.png"

實(shí)質(zhì)上上傳文件Requestbody對(duì)應(yīng)的請(qǐng)求頭就是 name="file0"; filename="test.png",只要拼對(duì)了就沒有問題了靴拱。

注意:

  1. name="file0"; filename="test.png"這個(gè)請(qǐng)求頭是根據(jù)有心課堂提供的上傳接口寫的垃喊,不適用其他上傳接口,但原理是類似的袜炕;
  2. 單張圖片上傳通用的請(qǐng)求頭是:name="file"; filename="test.png"
  3. filename="test.png"這個(gè)一般是指(你希望)保存在服務(wù)器的文件名字本谜。

舉例說明

比如我們這樣寫請(qǐng)求頭信息,如下代碼所示:

upload13.png

運(yùn)行請(qǐng)求抓包請(qǐng)求頭信息如下圖所示:

upload14.png

出現(xiàn)了name="name="file1"這樣的字段偎窘,拼接錯(cuò)誤(不用加name字段)乌助,服務(wù)器也毫不留情的返回了錯(cuò)誤:

upload15.png

這個(gè)問題我當(dāng)初沒有發(fā)現(xiàn),后來還是請(qǐng)教了Stay才搞明白了陌知。

好了他托,不知道我講的大家明白了沒有,最后來個(gè)成功運(yùn)行的請(qǐng)求抓包截圖吧:

upload16.png

關(guān)于文字類參數(shù)上傳

寫到最后忘了說文字參數(shù)了仆葡,文字參數(shù)相對(duì)文件來說容易些赏参。

在接口中,我們有一個(gè)文字參數(shù) @Part("data") String des,如果你需要多個(gè)登刺,增加就行了。需要注意的是這個(gè)參數(shù)的名字比如"data"嗡呼,不是前端自定義纸俭,而是后臺(tái)定義的。

代碼托管地址:https://github.com/stay4it/RetrofitTutorial

2016.8.19 凌晨

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末南窗,一起剝皮案震驚了整個(gè)濱河市揍很,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌万伤,老刑警劉巖窒悔,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異敌买,居然都是意外死亡简珠,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門虹钮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來聋庵,“玉大人,你說我怎么就攤上這事芙粱〖烙瘢” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵春畔,是天一觀的道長(zhǎng)脱货。 經(jīng)常有香客問我,道長(zhǎng)律姨,這世上最難降的妖魔是什么振峻? 我笑而不...
    開封第一講書人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮择份,結(jié)果婚禮上铺韧,老公的妹妹穿的比我還像新娘。我一直安慰自己缓淹,他們只是感情好哈打,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著讯壶,像睡著了一般料仗。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上伏蚊,一...
    開封第一講書人閱讀 51,679評(píng)論 1 305
  • 那天立轧,我揣著相機(jī)與錄音,去河邊找鬼。 笑死氛改,一個(gè)胖子當(dāng)著我的面吹牛帐萎,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播胜卤,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼疆导,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了葛躏?” 一聲冷哼從身側(cè)響起澈段,我...
    開封第一講書人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎舰攒,沒想到半個(gè)月后败富,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡摩窃,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年兽叮,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片猾愿。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡充择,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出匪蟀,到底是詐尸還是另有隱情椎麦,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布材彪,位于F島的核電站观挎,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏段化。R本人自食惡果不足惜嘁捷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望显熏。 院中可真熱鬧雄嚣,春花似錦、人聲如沸喘蟆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蕴轨。三九已至港谊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間橙弱,已是汗流浹背歧寺。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來泰國(guó)打工燥狰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人斜筐。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓龙致,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親顷链。 傳聞我的和親對(duì)象是個(gè)殘疾皇子目代,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,163評(píng)論 25 707
  • 整體Retrofit內(nèi)容如下: 1、Retrofit解析1之前哨站——理解RESTful2蕴潦、Retrofit解析2...
    隔壁老李頭閱讀 15,083評(píng)論 4 39
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理像啼,服務(wù)發(fā)現(xiàn)俘闯,斷路器潭苞,智...
    卡卡羅2017閱讀 134,659評(píng)論 18 139
  • 分享微博博主思想聚焦的《西游2》影評(píng) 《我可能看了個(gè)假西游此疹。很多人說...》 思想聚焦 ...
    胡小安閱讀 272評(píng)論 2 1
  • 夏日的一個(gè)清晨,天氣格外晴朗遮婶,朝陽一如既往地爬上了地平線蝗碎,叫醒了這座沉睡的城市。 他看了看手上的表旗扑,已經(jīng)不早了蹦骑,...
    峻銘閱讀 532評(píng)論 0 0