不知道你們在工做中有沒有碰到過在代碼級別中進行上傳和下載呢,通常的場景爲調用第三方的接口進行上傳大文件和下載大文件。html
我一個小夥伴最近在工做中就碰到了,他須要在代碼中調用第三方http接口進行原始文件的上傳,而後須要調用第三方接口把第三方服務處理好的數據文件下載到本地。他說其實沒什麼技術難度,百度了下,代碼示例也不少,httpclient就支持上傳文件和下載,就是代碼寫的太多了,不怎麼優雅。java
他給我看了httpclient的上傳代碼:git
String uploadUrl = "http://xxxxx.com/upload"; HttpPost httpPost = new HttpPost(uploadUrl); FileBody fileBody = new FileBody(new File("C:/Users/Administrator/Desktop/source.excel")); MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create(); multipartEntityBuilder.addPart("file",fileBody); // 設置其餘參數 List<NameValuePair> nvps = new ArrayList<NameValuePair>(); nvps.add(new NameValuePair("Accept","application/json, text/plain, */*")); nvps.add(new NameValuePair("Accept-Encoding","gzip, deflate, br")); nvps.add(new NameValuePair("Accept-Language","zh-CN,zh;q=0.9")); nvps.add(new NameValuePair("Connection","keep-alive")); nvps.add(new NameValuePair("Content-Length","28700")); nvps.add(new NameValuePair("Content-Type","multipart/form-data; boundary=----WebKitFormBoundarypaEfQmIQBbUrkI0c")); nvps.add(new NameValuePair("Host","xxxxx.com")); nvps.add(new NameValuePair("Origin","http://xxxxx.com")); nvps.add(new NameValuePair("Referer","xxxxx.com/admin/goods_edit.html")); nvps.add(new NameValuePair("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36")); HttpEntity reqEntity = multipartEntityBuilder.build(); httpPost.setEntity(reqEntity); try { CloseableHttpResponse response = httpClient.execute(httpPost); System.out.println("上傳以後返回的狀態碼:"+response.getStatusLine().getStatusCode()); try { HttpEntity resEntity = response.getEntity(); respStr = getRespString(resEntity); EntityUtils.consume(reqEntity); } catch (Exception e) { e.printStackTrace(); } finally { response.close(); } } catch (IOException e) { e.printStackTrace(); } System.out.println("resp=" + respStr);
由於要從代碼裏進行上傳遠端,須要創建一個MultipartEntityBuilder,設置各類header,小夥伴問我有什麼框架能夠提供更加優雅的寫法。spring
其實不少框架都有更加簡潔的API,可是我仍是推薦給了他最近一款比較火的框架:Forest
json
這個框架我之前也有寫文推薦過:一款直擊痛點的優秀http框架,讓我超高效率完成了和第三方接口的對接segmentfault
Forest
是一款主要致力於http請求各個場景的工具框架,基本上幾行代碼就能夠解決幾乎大部分的http的場景,api主打易用性,提供了不少特性,符合國內開發者的習慣,並且做者更新也比較勤快。目前的穩定release版本可用於生產環境。api
項目主頁地址:https://gitee.com/dt_flys/forest數組
Forest
能解決大部分http場景中的問題,對於上傳下載,做者在最新的版本中提供了上傳下載功能,可以以最簡單的方式實現,極大程度方便了開發者。springboot
對於想了解Forest
其餘功能的童鞋,能夠去項目主頁或者我以前寫的文章瞭解下。這裏僅介紹用Forest
上傳和下載的新特性。app
這裏以springboot項目爲例,依賴Forest
:
<dependency> <groupId>com.dtflys.forest</groupId> <artifactId>spring-boot-starter-forest</artifactId> <version>1.4.6</version> </dependency>
定義RemoteDataHander
接口:
public interface RemoteDataHander{ @Post(url = "http://xxxxx.com/upload") void upload(@DataFile("file") File file, OnProgress onProgress); @Get(url = "http://xxxxx.com/report/xxx.zip") @DownloadFile(dir = "${0}") void downloadFile(String dir, OnProgress onProgress); }
這個接口會被Forest
掃描組件在啓動時掃描到並註冊進spring容器,而後就能夠像使用本地方法同樣去調用進行上傳和下載操做了。
參數中聲明的OnProgress
參數,是一個接口,你能夠去實現它去完成進度的回調:
File file = myClient.downloadFile("D:\\TestDownload", progress -> { System.out.println("total bytes: " + progress.getTotalBytes()); // 文件大小 System.out.println("current bytes: " + progress.getCurrentBytes()); // 已下載字節數 System.out.println("progress: " + Math.round(progress.getRate() * 100) + "%"); // 已下載百分比 if (progress.isDone()) { // 是否下載完成 System.out.println("-------- Download Completed! --------"); } });
上傳和下載均可以去實現OnProgress
的,固然你也能夠不傳。
除了上述例子的用法,Forest
也支持其餘類型的文件參數和返回參數,如文件流,字節數組,MultipartFile類型等等。用法以下:
上傳:
/** * File類型對象 */ @Post(url = "http://xxxxx.com/upload") Map upload(@DataFile("file") File file, OnProgress onProgress); /** * byte數組 * 使用byte數組和Inputstream對象時必定要定義fileName屬性 */ @Post(url = "http://xxxxx.com/upload") Map upload(@DataFile(value = "file", fileName = "${1}") byte[] bytes, String filename); /** * Inputstream 對象 * 使用byte數組和Inputstream對象時必定要定義fileName屬性 */ @Post(url = "http://xxxxx.com/upload") Map upload(@DataFile(value = "file", fileName = "${1}") InputStream in, String filename); /** * Spring Web MVC 中的 MultipartFile 對象 */ @PostRequest(url = "http://xxxxx.com/upload") Map upload(@DataFile(value = "file") MultipartFile multipartFile, OnProgress onProgress); /** * Spring 的 Resource 對象 */ @Post(url = "http://xxxxx.com/upload") Map upload(@DataFile(value = "file") Resource resource);
下載:
/** * 返回類型用byte[],可將下載的文件轉換成字節數組 */ @GetRequest(url = "http://localhost:8080/images/test-img.jpg") byte[] downloadImageToByteArray(); /** * 返回類型用InputStream,用流的方式讀取文件內容 */ @Request(url = "http://localhost:8080/images/test-img.jpg") InputStream downloadImageToInputStream();
其中下載返回的字節數組和輸入流,能夠用於自定義操做
從使用者角度去出發,Forest
給了一個很是友好的api,並且聲明和配置都很是簡單。極大程度的方便了開發者。不光上傳下載場景,在其餘經常使用的http的調用場景中,Forest
也面面俱到,是一個http層面一站式解決式工具。有興趣的同窗能夠去看看,必定會提升你http場景的開發效率。
我也曾和做者探討過當下http領域的一些框架以及Forest
的發展路線。做者比較謙虛,回答了我一些問題
做者一直都表示,但願把各類http的場景作到極致,使開發者真正能用幾行代碼就能優雅的實現複雜的http的場景,作開源項目不易,爲這種工匠精神點贊。但願forest之後能爲更多開發者在工做中解決痛點。
我是鉑賽東,一個認真溫暖且執着的男生,我堅持作原創的技術科技分享號,關注「元人部落」,我每週會出一篇實用的原創技術文章,陪着你一塊兒走,再也不懼怕。