代码级别的上传下载神器

作者:元人部落
原文链接:
前言不知道大家在工作中有没有碰到过在代码级别中进行上传和下载呢 , 一般的场景为调用第三方的接口进行上传大文件和下载大文件 。
我一个小伙伴最近在工作中就碰到了 , 他需要在代码中调用第三方http接口进行原始文件的上传 , 然后需要调用第三方接口把第三方服务处理好的数据文件下载到本地 。 他说其实没什么技术难度 , 百度了下 , 代码示例也很多 , httpclient就支持上传文件和下载 , 就是代码写的太多了 , 不怎么优雅 。
他给我看了httpclient的上传代码:
StringuploadUrl="";HttpPosthttpPost=newHttpPost(uploadUrl);FileBodyfileBody=newFileBody(newFile("C:/Users/Administrator/Desktop/source.excel"));MultipartEntityBuildermultipartEntityBuilder=MultipartEntityBuilder.create();multipartEntityBuilder.addPart("file",fileBody);//设置其他参数Listnvps=newArrayList();nvps.add(newNameValuePair("Accept","application/json,text/plain,*/*"));nvps.add(newNameValuePair("Accept-Encoding","gzip,deflate,br"));nvps.add(newNameValuePair("Accept-Language","zh-CN,zh;q=0.9"));nvps.add(newNameValuePair("Connection","keep-alive"));nvps.add(newNameValuePair("Content-Length","28700"));nvps.add(newNameValuePair("Content-Type","multipart/form-data;boundary=----WebKitFormBoundarypaEfQmIQBbUrkI0c"));nvps.add(newNameValuePair("Host","xxxxx.com"));nvps.add(newNameValuePair("Origin",""));nvps.add(newNameValuePair("Referer","xxxxx.com/admin/goods_edit.html"));nvps.add(newNameValuePair("User-Agent","Mozilla/5.0(WindowsNT6.1;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/65.0.3325.146Safari/537.36"));HttpEntityreqEntity=multipartEntityBuilder.build();httpPost.setEntity(reqEntity);try{CloseableHttpResponseresponse=httpClient.execute(httpPost);System.out.println("上传之后返回的状态码:"+response.getStatusLine().getStatusCode());try{HttpEntityresEntity=response.getEntity();respStr=getRespString(resEntity);EntityUtils.consume(reqEntity);}catch(Exceptione){e.printStackTrace();}finally{response.close();}}catch(IOExceptione){e.printStackTrace();}System.out.println("resp="+respStr);因为要从代码里进行上传远端 , 需要建立一个MultipartEntityBuilder , 设置各种header , 小伙伴问我有什么框架可以提供更加优雅的写法 。
其实很多框架都有更加简洁的API , 但是我还是推荐给了他最近一款比较火的框架:Forest
这个框架我以前也有写文推荐过:一款直击痛点的优秀http框架 , 让我超高效率完成了和第三方接口的对接
Forest是一款主要致力于http请求各个场景的工具框架 , 基本上几行代码就可以解决几乎大部分的http的场景 , api主打易用性 , 提供了很多特性 , 符合国内开发者的习惯 , 而且作者更新也比较勤快 。 目前的稳定release版本可用于生产环境 。
项目主页地址:
对于想了解Forest其他功能的童鞋 , 可以去项目主页或者我之前写的文章了解下 。 这里仅介绍用Forest上传和下载的新特性 。
这里以springboot项目为例 , 依赖Forest:
com.dtflys.forestspring-boot-starter-forest1.4.6定义RemoteDataHander接口:
publicinterfaceRemoteDataHander{@Post(url="")voidupload(@DataFile("file")Filefile,OnProgressonProgress);@Get(url="/report/xxx.zip")@DownloadFile(dir="${0}")voiddownloadFile(Stringdir,OnProgressonProgress);}这个接口会被Forest扫描组件在启动时扫描到并注册进spring容器 , 然后就可以像使用本地方法一样去调用进行上传和下载操作了 。
参数中声明的OnProgress参数 , 是一个接口 , 你可以去实现它去完成进度的回调:
Filefile=myClient.downloadFile("D:TestDownload",progress->{System.out.println("totalbytes:"+progress.getTotalBytes());//文件大小System.out.println("currentbytes:"+progress.getCurrentBytes());//已下载字节数System.out.println("progress:"+Math.round(progress.getRate()*100)+"%");//已下载百分比if(progress.isDone()){//是否下载完成System.out.println("--------DownloadCompleted!--------");}});上传和下载都可以去实现OnProgress的 , 当然你也可以不传 。
一些其他参数的用法除了上述例子的用法 , Forest也支持其他类型的文件参数和返回参数 , 如文件流 , 字节数组 , MultipartFile类型等等 。 用法如下:
上传:
/***File类型对象*/@Post(url="")Mapupload(@DataFile("file")Filefile,OnProgressonProgress);/***byte数组*使用byte数组和Inputstream对象时一定要定义fileName属性*/@Post(url="")Mapupload(@DataFile(value="https://pcff.toutiao.jxnews.com.cn/p/20200908/file",fileName="${1}")byte[]bytes,Stringfilename);/***Inputstream对象*使用byte数组和Inputstream对象时一定要定义fileName属性*/@Post(url="")Mapupload(@DataFile(value="https://pcff.toutiao.jxnews.com.cn/p/20200908/file",fileName="${1}")InputStreamin,Stringfilename);/***SpringWebMVC中的MultipartFile对象*/@PostRequest(url="")Mapupload(@DataFile(value="https://pcff.toutiao.jxnews.com.cn/p/20200908/file")MultipartFilemultipartFile,OnProgressonProgress);/***Spring的Resource对象*/@Post(url="")Mapupload(@DataFile(value="https://pcff.toutiao.jxnews.com.cn/p/20200908/file")Resourceresource);下载:
/***返回类型用byte[] , 可将下载的文件转换成字节数组*/@GetRequest(url="http://localhost:8080/images/test-img.jpg")byte[]downloadImageToByteArray();/***返回类型用InputStream , 用流的方式读取文件内容*/@Request(url="http://localhost:8080/images/test-img.jpg")InputStreamdownloadImageToInputStream();【代码级别的上传下载神器】其中下载返回的字节数组和输入流 , 可以用于自定义操作
一些感受从使用者角度去出发 , Forest给了一个非常友好的api , 而且声明和配置都非常简单 。 极大程度的方便了开发者 。 不光上传下载场景 , 在其他常用的http的调用场景中 , Forest也面面俱到 , 是一个http层面一站式解决式工具 。 有兴趣的同学可以去看看 , 一定会提高你http场景的开发效率 。
我也曾和作者探讨过当下http领域的一些框架以及Forest的发展路线 。 作者比较谦虚 , 回答了我一些问题


    推荐阅读