后端接收前端上传的文件构造post请求调用上传文件的外部接口

14次阅读

共计 3980 个字符,预计需要花费 10 分钟才能阅读完成。

本文概述:
可能会存在一些需求,一些部署在内部的或者单独一个环境的服务,提供 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 等内容)

正文完
 0