前端將file文件傳給后臺(tái),后臺(tái)將文件傳給前臺(tái)(包含上傳下載)
在開發(fā)過程中,經(jīng)常會(huì)遇見對(duì)文件的處理。
例如:在上傳、下載文件時(shí),需要在前端選完文件傳到后臺(tái)傳到服務(wù)器;或者文件從后臺(tái),經(jīng)過特定需求的處理在返回給前臺(tái)。
中間處理過程各種各樣,但有兩個(gè)過程是固定的
- 前端傳給后臺(tái)
- 后臺(tái)返回給前端
經(jīng)常用到的上傳就是對(duì)應(yīng)第一步,下載對(duì)應(yīng)第二部。會(huì)在文章最后總結(jié)。
下面是示例代碼
-
前臺(tái)傳給后臺(tái)
界面采用el-upload組件,在選擇文件時(shí),將文件傳給后臺(tái)
<el-upload class="upload-demo" ref="upload" action="#" :on-change="changeFile" :file-list="fileList" :auto-upload="false" :limit="1"> <el-button slot="trigger" size="small" type="primary">選取文檔</el-button> </el-upload>
選擇完文件會(huì)走
changeFile(file)
方法,其中默認(rèn)入?yún)檫x中的文件,如下圖,真正的文件類型是File類型的raw變量不能直接將File類型變量傳輸,要把File文件轉(zhuǎn)成
FormData
類型,通過axios發(fā)送請(qǐng)求用的組件不同可能返回的類型、變量名不一樣,但最后要獲取到File文件類型,通過
FormData()
進(jìn)行轉(zhuǎn)換傳向后臺(tái)。需要配置的參數(shù):
- method:post
- url:自己的接口地址
- data:請(qǐng)求前轉(zhuǎn)換類型的參數(shù)
- headers:credentials: ‘same-origin’
- responseType:‘blob’ //用于接收后臺(tái)返回的文件所需類型
//el-upload文件上傳事件 changeFile(file) { let formData = new FormData() formData.append('file', file.raw)// 傳文件 axios({ method: 'post', url: url, //此處為往后臺(tái)發(fā)送請(qǐng)求的地址 data: formData, headers: { // "Content-Type": "multipart/form-data" credentials: 'same-origin' }, timeout: 20000, //設(shè)置返回接受類型為blob responseType: 'blob' }).then(res => { //返回值轉(zhuǎn)成Blob類型 let blob = new Blob([res.data]) }); },
后端用
MultipartFile
類接收,并且獲取HttpServletRequest
和HttpServletResponse
參數(shù),看下controller層的代碼@PostMapping("transferFile") public void transferFile(MultipartFile file, HttpServletRequest request, HttpServletResponse response) throws Exception { deptService.transferFile(file, request, response); }
可以看到成功獲取到在前臺(tái)選擇的文件
那后臺(tái)怎么返回給前臺(tái)呢
-
后臺(tái)將文件傳給前臺(tái)
接著上面,看下service實(shí)現(xiàn)類的代碼
@Override public void transferFile(MultipartFile file, HttpServletRequest request, HttpServletResponse response) throws IOException { InputStream inputStream = file.getInputStream(); String fileName = file.getOriginalFilename(); /** * 此處可以對(duì)文件輸入流按照需求進(jìn)行【自定義操作】 * 操作完后也要返回一個(gè)字節(jié)數(shù)組 */ byte[] bytes = new byte[1024]; inputStream.read(bytes); try { response.setCharacterEncoding("UTF-8"); //設(shè)置ContentType字段告知瀏覽器返回內(nèi)容類型 response.setContentType("application/octet-stream"); //設(shè)置Header字段 //下面這行代碼必須加,否則前端獲取不到Content-Disposition字段,即無法獲取文件名 response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); ServletOutputStream out = response.getOutputStream(); out.write(bytes); out.flush(); out.close(); } catch (Exception e) { } finally { inputStream.close(); } }
看上面代碼,通過
file.getInputStream()
方法獲取到文件的輸入流,在調(diào)用read()
方法,將其讀到字節(jié)數(shù)組中,response.setContentType("application/octet-stream")
設(shè)置返回值類型。通過response.getOutputStream()
方法,獲取返回的輸出流,調(diào)用write
將剛才讀到處理完的字節(jié)數(shù)組寫入,最后將流關(guān)閉。中間部分可以對(duì)流進(jìn)行自定義操作,操作完成后返回字節(jié)數(shù)組,寫到response的輸出流中即可
例如該項(xiàng)目中會(huì)將doc文件的流轉(zhuǎn)成docx格式的流,感興趣的可以看之后的文章。
接口執(zhí)行完成,前端將返回值轉(zhuǎn)成
Blob
類型,且發(fā)送請(qǐng)求時(shí)已經(jīng)設(shè)置了responseType為'blob'
。如下圖兩處關(guān)鍵點(diǎn)。
到此文件前后臺(tái)之間的傳輸過程就全部結(jié)束。
此處介紹的是個(gè)完整的過程,對(duì)于上傳和下載其實(shí)是兩步拆開單獨(dú)對(duì)應(yīng)。
-
上傳
完整的對(duì)應(yīng)第一步驟:選擇文件->傳遞給后臺(tái)->后臺(tái)轉(zhuǎn)成流調(diào)用第三方接口上傳到文件服務(wù)器
-
下載
通常從后臺(tái)調(diào)用第三方接口獲取文件,一般會(huì)以流的形式返回,此時(shí)為輸入流,然后拿到response的輸出流,寫入。
獲取遠(yuǎn)程文件輸入流->寫入響應(yīng)參數(shù)的輸出流
ServletOutputStream out = response.getOutputStream(); out.write(bytes);
com.google.api.client.util下有個(gè)工具類可以直接實(shí)現(xiàn)流之間的復(fù)制,省去多樣步驟文章來源:http://www.zghlxwxcb.cn/news/detail-676746.html
IOUtils.copy(inputStream, response.getOutputStream());
文章來源地址http://www.zghlxwxcb.cn/news/detail-676746.html
到了這里,關(guān)于前端將file文件傳給后臺(tái),后臺(tái)將文件傳給前臺(tái)(包含上傳下載)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!