本文概述:
可能会存在一些需求,一些部署在内部的或者单独一个环境的服务,提供rest服务。由后端来发送http请求来调用这些接口。那在后端就需要构造http请求。本文要解决的场景如下:
前端multipartfile 上传文件,后端接收后构造post请求,调用外部接口,传送文件流及其他参数
内容包括:
1.前端postman调用上传接口
2.后端接收multipartfile文件
3.后端用httpclient构造post请求
4.调用外部接口后返回结果的处理
先上代码:
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
/** *前端上传文件,后端接收后构造post请求,调用外部文件上传接口 */ @PostMapping(value = "uploadImage") public void uploadImage(Model model, @RequestParam(value = "image") MultipartFile image, String label) { log.info("=============uploadImage start================="); log.info("图像处理的标签"+label); Map<String, Object> data = new HashMap<String, Object>(); log.info("开始post请求构造======"); String url ="http://ip:port/mytest/fileup";//服务端要调用的外部接口 Map<String, String> resultMap = new HashMap<String, String>(); //httpclients构造post请求 CloseableHttpClient httpClient = HttpClients.createDefault(); try { log.info("post请求的url"+url); HttpPost httpPost = new HttpPost(url); //HttpMultipartMode.RFC6532参数的设定是为避免文件名为中文时乱码 MultipartEntityBuilder builder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.RFC6532); String originFileName = null; originFileName = image.getOriginalFilename(); // File file1 = new File("/home/temp/下载/1200-560.jpg"); //测试外部接口直接上传本地图片 builder.addBinaryBody("image", image.getBytes(), ContentType.MULTIPART_FORM_DATA, originFileName);// 设置上传文件流(需要是输出流),设置contentType的类型 builder.addTextBody("label",label);//post请求中的其他参数 // log.info("上传图的标签label"+label); HttpEntity entity = builder.build(); httpPost.setEntity(entity); HttpResponse response = httpClient.execute(httpPost);// 执行提交 HttpEntity responseEntity = response.getEntity();//接收调用外部接口返回的内容 if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){// String imageUrl = stringStringMap.get("data"); // data.put("path",imageUrl); // 返回的内容都在content中 InputStream content = responseEntity.getContent(); byte[] bytes = toByteArray(content); //将byte数组进行base64编码,此例中调用外部接口返回的是图片流 String encodeStr = Base64.getEncoder().encodeToString(bytes); model.addAttribute("data",encodeStr); } } catch (Exception e) { model.addAttribute("code", "错误码"); model.addAttribute("message","错误的提示信息"); }finally {//处理结束后关闭httpclient的链接 try { httpClient.close(); } catch (IOException e) { e.printStackTrace(); } } } /** *将输入流转换为输出流,无需创建临时文件 * @param input * @return * @throws IOException */ public byte[] toByteArray(InputStream input) throws IOException { ByteArrayOutputStream output = new ByteArrayOutputStream(); copy(input, output); return output.toByteArray(); }
postman调用接口如下
可能存在的坑:
1.确保后端部署的网络与所调用的外部接口网络是通的
2.后端接收multipartfile文件后若不需处理就调用外部接口的话,可不用生成临时文件。可直接使用multipartfile对象自带的方法,获取byte流
3.构造的post请求,若涉及到文件的上传,要设置正确的contentType,如上文代码中所示
4.构造的post请求中,addBinaryBody()中传递的可以是一个file对象,也可以是流。【若是流则需是输出流】
5.byte数组转换为base64字符串,详情见上文代码备注部分
6.将输入流转换为输出流,不需要写临时文件,见上文代码
multipartfile对象与file的区别:
multipartfile是个接口,通常所说的multipartfile是在springmvc中设置过的。是springmvc中用来传递文件对象而定义的。该接口包括如下方法
byte[] bytes = multipartFile.getBytes();//获取multipartfile对象的byte数组,可转换文件流等 String contentType = multipartFile.getContentType();//获取multipartfile的头类型 InputStream inputStream = multipartFile.getInputStream();//获取输入流 String name = multipartFile.getName();//获取文件名 String originalFilename = multipartFile.getOriginalFilename();//获取初始文件名 long size = multipartFile.getSize();//获取文件大小 boolean empty = multipartFile.isEmpty();//判断对象内容是否是空 multipartFile.transferTo(new File("文件路径"));//指定一个文件路径,可将multipartfile对象中的内容写入文件。若需要转换为file对象,需要创建一个临时文件
MultipartFile是个接口,file可以通过设置CommonsMultipartFile对象的属性来进行转换。
springmvc中设置如下:
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="104857600"/>
<property name="maxInMemorySize" value="4096"/>
</bean>
springboot中设置上传文件的大小:
spring.http.multipart.maxFileSize=50Mb //单个文件可上传的最大size
spring.http.multipart.maxRequestSize=1000Mb //整个请求的最大size(还包括header等内容)