这是转载的文章,之因此转载,是由于原做者漏了一个hutool的import,致使我浪费了5个小时,而原做者的文章不能评论,特此转载+说明。前端
就是这行代码坑了我5个小时:
import cn.hutool.core.io.resource.InputStreamResource;java
最近不少朋友在go-fastdfs的微信群里面问道,go-fastdfs何时支持流上传?其实一直都支持的!为何这样子说呢?由于go-fastdfs自己就是基于http协议进行传输的,那么若是有读者对Java的HttpURLConnection的源码研究过的话,会发现其内部也是能够经过conn.getInputStream()和conn.getOutputStream()获取其输入输出流,一般能够直接往outputStream里面写入符合http协议的数据。那么根据这个特色,在Java里面,直接经过流的形式(一般是从MultipartFile里面获取InputStream)再上传到go-fastdfs是没问题的。跟http协议相关的知识点包括http协议报文格式和上传二进制数据等若是不了解能够先自行百度一下。这里不会细讲的哦。git
引起认为go-fastdfs不能直接流上传的缘由
通过本人的分析认为,让广大读者认为不能直接使用流上传的缘由应该是go-fastdfs的github的代码示例形成一些误会。不过官方的代码示例并无错误,只是直接从本地读取文件系统的文件,造成File对象进行上传。针对使用Spring等框架接收前端上传过来的文件再进行转发上传到go-fastdfs的用户,就可能会有疑惑。由于获取到的是MultipartFile,而非java.io.File。github
Hutool-http、HttpClient、OkHttp3多种方式流式文件上传
因为有很多人问到上面的问题,如今本人总结了一个经常使用的几种http客户端文件流式上传的方式,至关于给本身作下记录,同时也给有这方面疑问的朋友一个借鉴。废话很少说,直接上代码吧。代码是基于springboot的maven工程。spring
Hutool-http方式
先在pom中添加hutool的依赖apache
<dependency>json
<groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>4.5.1</version>
</dependency>
接着在Controller中代码示例springboot
import cn.hutool.core.io.resource.InputStreamResource; @RequestMapping("/upload") public String upload(MultipartFile file) { String result = ""; try { InputStreamResource isr = new InputStreamResource(file.getInputStream(), file.getOriginalFilename()); Map<String, Object> params = new HashMap<>(); params.put("file", isr); params.put("path", "86501729"); params.put("output", "json"); String resp = HttpUtil.post(UPLOAD_PATH, params); Console.log("resp: {}", resp); result = resp; } catch (IOException e) { e.printStackTrace(); } return result; }
HttpClient方式
pom依赖微信
<dependency>并发
<groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId> <artifactId>httpmime</artifactId>
</dependency>
接着在Controller中代码示例
@RequestMapping("/upload1") public String upload1(MultipartFile file) { String result = ""; try { CloseableHttpClient httpClient = HttpClientBuilder.create().build(); CloseableHttpResponse httpResponse = null; RequestConfig requestConfig = RequestConfig.custom() .setConnectTimeout(200000) .setSocketTimeout(2000000) .build(); HttpPost httpPost = new HttpPost(UPLOAD_PATH); httpPost.setConfig(requestConfig); MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create() .setMode(HttpMultipartMode.BROWSER_COMPATIBLE) .setCharset(Charset.forName("UTF-8")) .addTextBody("output", "json") .addBinaryBody("file", file.getInputStream(), ContentType.DEFAULT_BINARY, file.getOriginalFilename()); httpPost.setEntity(multipartEntityBuilder.build()); httpResponse = httpClient.execute(httpPost); if (httpResponse.getStatusLine().getStatusCode() == 200) { String respStr = EntityUtils.toString(httpResponse.getEntity()); System.out.println(respStr); result = respStr; } httpClient.close(); httpResponse.close(); } catch (Exception e) { e.printStackTrace(); } return result; }
OkHttp3上传示例
pom文件依赖
<dependency>
<groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>3.9.1</version>
</dependency>
接着在Controller中代码示例
@RequestMapping("/upload2") public String upload2(MultipartFile file) { String result = ""; try { OkHttpClient httpClient = new OkHttpClient(); MultipartBody multipartBody = new MultipartBody.Builder(). setType(MultipartBody.FORM) .addFormDataPart("file", file.getOriginalFilename(), RequestBody.create(MediaType.parse("multipart/form-data;charset=utf-8"), file.getBytes())) .addFormDataPart("output", "json") .build(); Request request = new Request.Builder() .url(UPLOAD_PATH) .post(multipartBody) .build(); Response response = httpClient.newCall(request).execute(); if (response.isSuccessful()) { ResponseBody body = response.body(); if (body != null) { result = body.string(); System.out.println(result); } } } catch (Exception e) { e.printStackTrace(); } return result; }
总结上面给出了几个示例,是否是都挺简单的?经过这种方式,就能够在Controller中作中转了,仍是挺方便的。顺便提一下,上面几种方式中,我我的以为Hutool的是最简单的,最方便的,对于HttpClient而言,概念比较多,显得相对复杂,OkHttp也同样,不过比HttpClient显得优雅点。针对通常的并发量,我的以为hutool的Http已经够用了,底层是基于jdk的HttpUrlConnection实现的。若是对性能有特殊要求的,能够考虑httpclient或者OKHttp,后二者相对而言,更推荐使用OkHttp。