概述
- 本文只是回顧這樣一次經(jīng)歷,所以不會貼大段大段代碼
- 當(dāng)時拿到的需求是,先在手機上寫好簽名,然后上傳到服務(wù)器持久化到數(shù)據(jù)庫,最后供web和移動端以圖片的形式展示出來。
過程
第一反應(yīng)是這功能有啥用,默默地吐槽完領(lǐng)導(dǎo)后開始考慮怎么去實現(xiàn)。
需求的理解
- 最先想到的是手機輸入法的手寫功能,去訊飛看了一下,基本上都是說的語音識別(因為最近人工智能很火),沒找到手寫相關(guān)的API。正苦惱的時候發(fā)現(xiàn)自己思路跑偏了,既然是要簽名,手寫的給識別出來了就沒意義了(簽名就是要認不出來)。”寫啥樣就要存啥樣”,這不就是畫畫嘛。
- 于是轉(zhuǎn)向了canvas。其實對canvas我的了解僅僅局限于這是能在頁面上畫畫的。接下來就是去找ionic有沒有相關(guān)的插件,結(jié)果找到了
signature_pad.js,更幸福的是,已經(jīng)有人在ionic上用過。
如何實現(xiàn)
- 在github上作者也詳細介紹了怎么使用,如何導(dǎo)出成圖片。實踐的過程中發(fā)現(xiàn)可以導(dǎo)出為
.jpg,.png,.svg三種格式。但是導(dǎo)出的內(nèi)容是”dataurl”,對于在此之前僅僅知道圖片本質(zhì)也是二進制的我而言,新的問題出現(xiàn)了。怎么把dataurl轉(zhuǎn)換成真正的圖片呢? - 這時候需求增加了。需要在手機端本地存儲這張圖片,以便以后直接調(diào)用,減少一次請求。
- 這實際上還是之前的問題,dataurl→圖片。”內(nèi)事不決問百度”。經(jīng)過一番搜索后,發(fā)現(xiàn)dataurl可以轉(zhuǎn)為Blob對象,通過Blob對象能夠生成一個文件。
ionic本地文件系統(tǒng)
-
在ionic中獲取設(shè)備文件系統(tǒng),進而取得文件路徑,最后寫入文件內(nèi)容,這個問題已經(jīng)解決了。通過
cordova-plugin-file這個插件就能解決該問題。 - 到這個時候,我認為問題已經(jīng)完全解決了,既然dataurl在手機本地能夠直接轉(zhuǎn)為圖片,那么在服務(wù)器上自然也能轉(zhuǎn)為圖片,最后再把圖片路徑持久化到數(shù)據(jù)庫就萬事大吉了。中間需要解決就是把dataurl發(fā)送到服務(wù)器。
圖片上傳到后臺
- 最開始我覺得這都不是問題,發(fā)數(shù)據(jù)到服務(wù)器,post請求不就完事了。接下來,通過Angular的http模塊,設(shè)置header為
applicant/x-www-form-urlencoded,再服務(wù)端通過文件上傳API生成了圖片。問題又來了。 - dataurl在本地與在服務(wù)器生成的圖片竟然不一樣。于是在chrome控制臺看請求響應(yīng)信息。把請求中的dataurl拿出來在服務(wù)器直接本地測試,生成的圖片又是正確的。最后在服務(wù)器打斷點debug,發(fā)現(xiàn)服務(wù)器接受到的dataurl是客戶端發(fā)送的dataurl截取后的值。
- dataurl一般會很長,可能會達到10000個字符。經(jīng)過百度后發(fā)現(xiàn),post請求本身對長度是沒有限制的,但是服務(wù)器會有,tomcat就有這方面的參數(shù)可以設(shè)置。但是服務(wù)器一般配置好了不會輕易更改,因此還是只能從自身來找解決方案。
form表單的提交方式
- 在MDN上查看Using_XMLHttpRequest相關(guān)的頁面上了解到,form表單有四種提交方式
-
method=post, enctype=applicant/x-www-form-urlencoded這是表單提交的默認方式 -
method=post, enctype=multipart/form-data文件上傳時表單的提交方式 method=post, enctype=text/plain-
method=get這種情況下enctype會被忽略
-
- 這時候我突然想到,圖片上傳到服務(wù)器的過程中,圖片數(shù)據(jù)是以什么形式存在的呢?我嘗試直接把dataurl放到
img標(biāo)簽的src屬性中,果然,直接把圖片顯示出來了。那么文件上傳時,圖片數(shù)據(jù)可能就是把dataurl直接發(fā)送到后臺,而且因為是文件上傳,那么服務(wù)器對于請求數(shù)據(jù)的大小應(yīng)該是沒有限制或者說限制的字節(jié)數(shù)會大得多
在沒有form表單的情況下構(gòu)造文件上傳
-
因為沒有form標(biāo)簽,沒有辦法直接通過表單提交的方式上傳圖片。有兩個備選方案:
- 通過js生成一個form表單
- 直接手動構(gòu)造一個文件上傳請求
-
方案一太麻煩,不夠直接。所以直接就采用了方案二。通過FormData的API可以直接構(gòu)造表單項。
let fd = new FormData(); fd.append("Filename", "signature.png"); fd.append("Filedata", params, "signature.png"); 然后在后臺方法中,直接將該dataurl寫到文件里面,就能夠生成一張
.png圖片了
感想
對需求的理解很重要。最開始拿到需求時,我的腦海里關(guān)鍵詞就是手寫。甚至都想這不是需要人工智能識別的嘛。很顯然這個思路就偏了。當(dāng)對需求的理解有偏差的時候,后面的實現(xiàn)必然會遇到各種問題。
-
對技術(shù)原理、實質(zhì)的認識是實現(xiàn)的關(guān)鍵。在這個過程中,
- 對圖片壓根不了解
- 對java上傳文件不熟悉
- 對表單相關(guān)API掌握的不夠深入
最后完成這個功能,我發(fā)現(xiàn)自己都完整寫了一遍最原始的java文件上傳代碼,文件流相關(guān)的代碼等等...
發(fā)散思維,自己不會就得找資料,現(xiàn)在開始學(xué)習(xí),一切都來得及。Never Too Old To Learn