和一个保险系统的对接. 文本类型的参数咱不多说, 因为接口数据源是保险订单和保险理赔, 所以需要传输一些图片和视频信息, 比如说合同发票,定损图片和视频等等. 这种需求的处理比较合适的方案是约定一个FTP/SFTP服务器, 然后参数中还传递文件的路径和名称, 然后接收方在接到推送之后,可以开异步或者放到MQ里面去慢慢下载. 提了建议,然而并没有什么卵用. 就直接传流呗, 而且还是存在同一个字段多个图片的情况, 比如说定损图片, 可能存在多张, 不确定, 那么这边存储的话就需要分表了, 单据和图片子表的根据单据类型(订单和理赔)和ID关联.
另外, 本公司(入职一年才交社保的公司)有专门提供给外面调用的SDK, 意思是写完接收接口, 还得在SDK里面把推送数据的业务完成, 然后给外面直接调用SDK的方法就完事了.
上代码, 省去授权部分
//Controller层
/**
*resources 接收实体
*type1-4Imp 接收图片和视频参数
*
**/
@PostMapping("/receDate")
@ApiOperation("***")
@AnonymousAccess
public ResponseEntity<Object> receDate(xx resources ,
List<MultipartFile> type1Imp,
List<MultipartFile> type2Imp,
List<MultipartFile> type3Imp,
List<MultipartFile> type4Imp){
HttpServletRequest httpServletRequest = RequestHolder.getHttpServletRequest();
// httpServletRequest授权用的
return xxService.create(resources, type1Imp, type2Imp, type3Imp, type4Imp, httpServletRequest);
}
//Service层
public ResponseEntity create(xx resources ,
List<MultipartFile> type1Imp,
List<MultipartFile> type2Imp,
List<MultipartFile> type3Imp,
List<MultipartFile> type4Imp,
HttpServletRequest httpServletRequest) {
//... 授权处理
//根据唯一ID判断是更新还是新增
1. 新增:
保存xx,返回ID
备份流到OSS存储返回文件地址
保存子表type1Imp-type4Imp路径,
2. 更新:
查出子表存在的文件, 删除OSS文件和子表记录
更新xx, 保存携带的流信息
}
SDK引了两个包
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.11</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.11</version>
</dependency>
SDK方法
/**
* url推送地址
* param文本类型参数
* cookies
* header 请求头
* inputSs 文件流集合 外层key对应接口接收字段名, 内层key可以是文件名称或者文件链接, 看需求
**/
public String sendFilePost(String url, Map<String,String> param, Map<String,String> cookie, Map<String,String> header, Map<String , Map<String, InputStream>> inputSs) throws Exception {
logger.info("请求地址:"+url);
HttpPost postMethod = new HttpPost(url);
if(header!=null && header.size()>0){
for(String key: header.keySet()){
postMethod.addHeader(key,header.get(key));
}
}
postMethod = HttpPostGetUtil.postParams(postMethod);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setCharset(java.nio.charset.Charset.forName("UTF-8"));
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
if(inputSs != null && inputSs.size() > 0){
for(String type:inputSs.keySet()){
Map<String, InputStream> stringInputStreamMap = inputSs.get(type);
if(stringInputStreamMap.size() > 0){
for(String fileName: stringInputStreamMap.keySet()){
builder.addBinaryBody(type, stringInputStreamMap.get(fileName), ContentType.MULTIPART_FORM_DATA, fileName);// 文件流
}
}else{
continue;
}
}
}
//解决中文乱码
ContentType contentType = ContentType.create(HTTP.PLAIN_TEXT_TYPE, HTTP.UTF_8);
for(String key:param.keySet()){ // 字段没值不传,
if(param.get(key)!=null && param.get(key).length()>0){
builder.addTextBody(key, param.get(key), contentType);
}
}
HttpEntity entity = builder.build();
postMethod.setEntity(entity);
if(cookie!=null && cookie.size()>0){
StringBuffer cookieStr = new StringBuffer("");
for(String key: cookie.keySet()){
cookieStr.append(key).append("=").append(cookie.get(key)).append(";");
}
postMethod.setHeader("Cookie", cookieStr.toString());
}
//发送请求
CloseableHttpResponse response = httpclient().execute(postMethod);
//都是伪代码, 提供思路
测试SDK调用:
public static void bdTest2() throws Exception {
YwServiceI ywServiceI=new YwServiceI();
...省去授权部分
Map<String,String> params=new HashMap<String,String>();
params.put("xx1","123");
...加工文本类型参数
params.put("xxn","nnn");
File f1=new File("D:\\a.txt"); //f1
File f2=new File("D:\\b.txt"); //f2
File f3=new File("D:\\c.txt"); //f3
File f4=new File("D:\\d.txt"); //f4
File f11=new File("D:\\aa.txt"); //f11
File f22=new File("D:\\bb.txt"); //f22
File f33=new File("D:\\cc.txt"); //f33
File f44=new File("D:\\dd.txt"); //f44
//加工数据流
Map<String, InputStream> x1= new HashMap<>();
x1.put("http://a.a.a/a.png",new FileInputStream(f1)); //图片链接放到key中
x1.put("http://aa.aa.aa/aa.png",new FileInputStream(f11));
Map<String, InputStream> x2= new HashMap<>();
x2.put("f2.fileurl",new FileInputStream(f2));
x2.put("f22.QWE",new FileInputStream(f22));
Map<String, InputStream> x3= new HashMap<>();
x3.put("f3.XXX",new FileInputStream(f3));
x3.put("f33",new FileInputStream(f33));
Map<String, InputStream> x4= new HashMap<>();
x4.put("f4.fileurl",new FileInputStream(f4));
x4.put("f44.fileurl",new FileInputStream(f44));
Map<String, Map<String, InputStream>> impMap= new HashMap<>();
impMap.put("type1Imp",x1); //主要这几个key要和接口接收的方法参数名保持一致
impMap.put("type2Imp",x2);
impMap.put("type3Imp",x3);
impMap.put("type4Imp",x4);
//推送数据
String s = ywServiceI.sendFilePost("http://localhost/xxx", params, null, header, impMap);
}
中间还有一个小插曲, 调试过程中, 对方图片数据流不是太容易获取到, 我说不行的话你可以先用这个方法试下, 因为有图片的网络地址,也是要传过来的, 试了下可以, 然后又觉得传的流太多了, 能不能地址传过来后我这边通过这个方式取流上传. 那咋可能呀兄弟, 第一我频发的请求图片服务, 你们给我限制, 甚至告了咋办,也没得授权. 第二一开始就提出了别的方案, 你们也不考虑呀 第三 这种不靠谱的流程他就是不靠谱 第四, 我接口接收之后 上传OSS用的MultipartFile格式, 那我还得转换.