代碼級別的上傳下載神器

前言

不知道你們在工做中有沒有碰到過在代碼級別中進行上傳和下載呢,通常的場景爲調用第三方的接口進行上傳大文件和下載大文件。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,可是我仍是推薦給了他最近一款比較火的框架:Forestjson

這個框架我之前也有寫文推薦過:一款直擊痛點的優秀http框架,讓我超高效率完成了和第三方接口的對接segmentfault

Forest 是一款主要致力於http請求各個場景的工具框架,基本上幾行代碼就能夠解決幾乎大部分的http的場景,api主打易用性,提供了不少特性,符合國內開發者的習慣,並且做者更新也比較勤快。目前的穩定release版本可用於生產環境。api

項目主頁地址:https://gitee.com/dt_flys/forest數組

image

用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的發展路線。做者比較謙虛,回答了我一些問題

image

image

做者一直都表示,但願把各類http的場景作到極致,使開發者真正能用幾行代碼就能優雅的實現複雜的http的場景,作開源項目不易,爲這種工匠精神點贊。但願forest之後能爲更多開發者在工做中解決痛點。

關注做者

我是鉑賽東,一個認真溫暖且執着的男生,我堅持作原創的技術科技分享號,關注「元人部落」,我每週會出一篇實用的原創技術文章,陪着你一塊兒走,再也不懼怕。

相關文章
相關標籤/搜索