功能描述:上传文件到文件服务器,返回文件在服务器地址,下载(获取)文件直接可以在浏览器拼接地址(ip:端口/返回文件在服务器地址)
一、feign上传下载
引入maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
1、上传接口
@FeignClient(name = "fileUploadAPI", url = "${file.uploadPath}")
public interface FileUploadAPI {
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
String uploadImage(@RequestPart(value = "img") MultipartFile img);
}
2、下载接口
@FeignClient(name = "FileDownAPI",url = "${file.downPath}")
public interface FileDownAPI {
@GetMapping(value = "{path}")
Response getImage(@PathVariable("path") String path);
}
下载文件api调用
private void downImage(String path, String parentFile) {
Response response = fileDownAPI.getImage(path);
Response.Body body = response.body();
try {
InputStream inputStream = body.asInputStream();
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
//路劲类似格式:/images/20220719/6204bc93415ec044c50f60ad5bcc132c.png
String[] split = path.split("\\/");
if (split.length == 4) {
File img = new File(parentFile + "/" + split[3]);
if (!img.exists()) {
img.createNewFile();
}
FileOutputStream fileOutputStream = new FileOutputStream(img);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
int length = 0;
byte[] bytes = new byte[1024 * 10];
while ((length = bufferedInputStream.read(bytes)) != -1) {
bufferedOutputStream.write(bytes, 0, length);
}
bufferedOutputStream.flush();
bufferedOutputStream.close();
bufferedInputStream.close();
inputStream.close();
} else {
throw new RuntimeException("图片路径格式不对,必须为:/***/***/**.jpg 格式");
}
} catch (IOException e) {
logger.error(e.getMessage());
throw new RuntimeException("获取文件失败", e);
}
}
这里之所以写两个接口是因为如果上传地址和下载地址不一致(端口开始就不一样)的情况
二、httpclient上传
引入依赖:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>
1、http协议文件上传
private static String inputFileByHttp(String uploadUrl) throws IOException {
// uploadUrl = "http://192.168.0.1:8080/images";
String localFile = "docs/test.txt";
File file = new File(localFile);
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost post = new HttpPost(uploadUrl);
MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
multipartEntityBuilder.setCharset(Charset.forName("UTF-8"));
//这两个都可以
// multipartEntityBuilder.addBinaryBody("img",fileInputStream,ContentType.MULTIPART_FORM_DATA,"test.txt");
multipartEntityBuilder.addBinaryBody("img", file);
HttpEntity httpEntity = multipartEntityBuilder.build();
post.setEntity(httpEntity);
CloseableHttpResponse response = httpClient.execute(post);
String result = "无数据返回";
if (200 == response.getStatusLine().getStatusCode()) {
HttpEntity entity = response.getEntity();
if (null != entity) {
result = EntityUtils.toString(entity, "UTF-8");
}
System.out.println(result);
}
return result;
}
2、https协议文件上传
private static String inputFileByHttps(String uploadUrl) throws IOException {
// uploadUrl = "https://baidu.xx.com:10000/images";
String localFile = "docs/test.txt";
File file = new File(localFile);
FileInputStream fileInputStream = new FileInputStream(file);
CloseableHttpClient httpClient = createSSLClient();
HttpPost post = new HttpPost(uploadUrl);
MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
multipartEntityBuilder.setCharset(Charset.forName("UTF-8"));
//这两个都可以
multipartEntityBuilder.addBinaryBody("img",fileInputStream,ContentType.MULTIPART_FORM_DATA,"test.txt");
// multipartEntityBuilder.addBinaryBody("img", file);
HttpEntity httpEntity = multipartEntityBuilder.build();
post.setEntity(httpEntity);
CloseableHttpResponse response = httpClient.execute(post);
String result = "无数据返回";
if (200 == response.getStatusLine().getStatusCode()) {
HttpEntity entity = response.getEntity();
if (null != entity) {
result = EntityUtils.toString(entity, "UTF-8");
}
System.out.println(result);
}
return result;
}
private static CloseableHttpClient createSSLClient() {
SSLContext sslContext;
try {
sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
//信任所有
@Override
public boolean isTrusted(X509Certificate[] xcs, String string) {
return true;
}
}).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
return HttpClients.custom().setSSLSocketFactory(sslsf).build();
} catch (KeyStoreException ex) {
ex.printStackTrace();
} catch (NoSuchAlgorithmException ex) {
ex.printStackTrace();
} catch (KeyManagementException ex) {
ex.printStackTrace();
}
return HttpClients.createDefault();
}
http和https综上代码可以看到在获取httpclient的时候有区别,https需要设置ssl信任
三、postman上面测试https协议文件上传设置
文件key必须要正确
关闭settings设置里面的ssl证书验证,一般默认是开启的
开启settings设置里面的CA证书,默认是关闭的
四、RestTemplate 通过https协议文件下载
1、引入依赖:或者feign的依赖包也可以,里面包含这个依赖
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>
2、创建bean,这里由于spring没有创建该实例,所以手动将该RestTemplate实例配置到sping容器。这里如果是http协议的话,直接return new RestTemplate(); 就可以,里面的代码实际就是配置https协议做准备
@Bean
public RestTemplate restTemplate() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;
SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom()
.loadTrustMaterial(null, acceptingTrustStrategy)
.build();
SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext);
CloseableHttpClient httpClient = HttpClients.custom()
.setSSLSocketFactory(csf)
.build();
HttpComponentsClientHttpRequestFactory requestFactory =
new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
return new RestTemplate(requestFactory);
}
3、调用下载
public void downFile(){
try {
String url=String.format("https://xxxx/20220801/9213b8102bd447b17b4da19174a20916.xlsx");
ResponseEntity<byte[]> exchange = restTemplate.exchange(new URI(url), HttpMethod.GET, new HttpEntity<>(new HttpHeaders()), byte[].class);
byte[] bytes = exchange.getBody();
File file = new File("exaple.xlsx");
FileOutputStream fileOutputStream = new FileOutputStream(file);
fileOutputStream.write(bytes, 0, bytes.length);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
实际上,如果不是要求多高的项目,就直接用RestTemplate远程调用最方便,属于spring-web jar包,而且还可以加上负载均衡注解@LoadBalance做负载
五、文件下载请求。下载文件到本地,以及文件名称为中文时出现下划线或者乱码情况
@RequestMapping(value = "getImgZip", method = RequestMethod.GET)
@ResponseBody
public void getImgZip(HttpServletResponse servletResponse) {
File file = new File("D://test-张三-2022-08-30.zip");
try {
String encode = URLEncoder.encode(file.getName(), "UTF-8");
servletResponse.setHeader("Content-disposition", "attachment;filename="+encode+";"+"filename*=utf-8''"+encode);
servletResponse.setContentType("application/octet-stream");
if (!(file.exists() && file.canRead())) {
throw new RuntimeException("zip文件不存在");
}
FileInputStream inputStream = null;
inputStream = new FileInputStream(file);
byte[] data = new byte[inputStream.available()];
inputStream.read(data);
inputStream.close();
OutputStream stream = servletResponse.getOutputStream();
stream.write(data);
stream.flush();
stream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
String encode = URLEncoder.encode(file.getName(), "UTF-8");
servletResponse.setHeader("Content-disposition", "attachment;filename="+encode+";"+"filename*=utf-8''"+encode);
主要是这两句:
String encode = URLEncoder.encode(file.getName(), "UTF-8");
编码为utf-8,
设置头部信息格式为:"Content-disposition", "attachment;filename=" + encode + ";" + "filename*=utf-8''" + encode
但是注意这里的encode后面补加的 +";"+"filename*=utf-8''"+encode 是关键