--- tags: Note, Fullstack --- # Upload Multiple Files > from Javascript to Python > 一般來說,要從前端上傳一個檔案到後端,最簡單的做法是: `<input type="file">`拿到一個檔案的`Blob` 用`application/octet-stream`直接往後端送,後端收到就會是一個二元字串,可以直接使用。 但這樣有個前提是,你一次只上傳**一個檔案**。 在現實情況很常有需要送很多資料的情況,這時候不是放在`query string`就是放在HTTP header; 若是資料很多的情況,這兩種做法都不現實,勢必變成需要夾在request body和檔案一起送。 常見的格式是JSON,但Javascript要如何處理把檔案轉成JSON? 1. 先用`FileReader`讀成`ArrayBuffer` ```javascript= function getArrayBuffer(file) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.addEventListener('load', () => { resolve(reader.result); }); reader.readAsArrayBuffer(file); }) } ``` 2. 再將`ArrayBuffer`轉成JSON字串,此時的字串是整數序列,例如:`[1,2,3]` ```javascript= var body = JSON.stringify({ context: Array.from(new Uint8Array(arrayBuffer)), }); ``` 3. 傳到後端就可以當成JSON解開,但是還需要做些手腳將整數序列倒轉回二元字串 ```python= context = request_body['context'] file_str = bytearray(context) ``` 4. 這樣就可以正常使用了,例如寫回檔案 ```python= with open('/tmp/context', 'wb') as f: f.write(file_str) ``` ## Append ArrayBuffer 在處理檔案上傳的時候,通常都會需要計算integrity,例如MD5。 在Javascript的世界目前[SparkMD5](https://github.com/satazor/js-spark-md5)算是一個常見的套件。 為了計算加速,要把大的檔案切成小的chunk,這時就會產生一個問題: > ArrayBuffer是**immutable**,不能被更改 > 這樣要如何組回一個完整的ArrayBuffer後送? 以下是一個例子: ```javascript= const appendBuffer = (buffer1, buffer2) => { var tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength); tmp.set(new Uint8Array(buffer1), 0); tmp.set(new Uint8Array(buffer2), buffer1.byteLength); return tmp.buffer; }; ``` ## Python unittest 另外一個問題是,在Python端,要如何產生用於unittest的受試JSON? 要做的事情就和Javascript有點相似,將檔案讀入然後轉成整數序列: ```python= with open('tests/fake_context', 'rb') as f: context = f.read() fake_req = { 'context': list(bytearray(context)) } ``` 這樣一個前端到後端完整的故事就搭上了,只能說,前端的水好深!
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up