场景
将系统内部的文件通过远程地址上传到第三方系统拿到第三方地址,我这里第三方还没有开放接口,苦逼地只能F12从第三方平台尝试他们接口的协议情况.记录下来是因为,这种虽然不是什么高深的技术用法,但是这种涉及基础的灵活使用总记不住,因为很多是固定写法,每次都要调不少时间,这次记录下,给我和大家参考下.
代码
/**
* 两个参数都不能为空,并且fileName必须要有后缀并且和文件的实际后缀一致
*
* @param ehrUrl
* @param fileName
* @return
*/
public String getMokaUrlByEhrUrl(String ehrUrl, String fileName) {
if (StringUtils.isAnyBlank(ehrUrl, fileName)) {
throw new BizProcessException("url和fileName都不能为空!");
}
String suffix = FileUtil.getSuffix(fileName);
if (StringUtils.isBlank(suffix)) {
throw new BizProcessException("文件名中的后缀不能为空!");
}
try {
//优先从库里查-尽量减少对moka外部接口的请求
EhrFileMessage ehrFileMessage = ehrFileMessageMapper.selectOne(
Wrappers.lambdaQuery(EhrFileMessage.class).select(EhrFileMessage::getMokaUrl)
.eq(EhrFileMessage::getEhrUrl, ehrUrl).last("limit 1"));
if (ehrFileMessage != null) {
return ehrFileMessage.getMokaUrl();
}
URIBuilder uriBuilder = new URIBuilder("https://xxx.com/api/workflow/v1/form/uploadAttachment");
uriBuilder.addParameter("bus", "20");
uriBuilder.addParameter("loginType", "10");
URI uri = uriBuilder.build();
int i = ehrUrl.lastIndexOf("/");
String encode = URLEncoder.encode(ehrUrl.substring(i + 1, ehrUrl.length()));
String ehrUrlEncode = ehrUrl.substring(0, i + 1) + encode;
URL url = new URL(ehrUrlEncode);
InputStream inputStream = url.openStream();
byte[] bytes = inputStream.readAllBytes();
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(uri);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addBinaryBody("file", bytes, ContentType.DEFAULT_BINARY, fileName);
HttpEntity multipart = builder.build();
httpPost.setEntity(multipart);
httpPost.setHeader("Cookie", "moka-uid=" + this.getMokaToken());
CloseableHttpResponse response = httpClient.execute(httpPost);
Integer statusCode =
Optional.ofNullable(response).map(CloseableHttpResponse::getStatusLine).map(StatusLine::getStatusCode)
.orElse(500);
if (statusCode == 200 && response.getEntity() != null) {
JSONObject jsonObject = JSON.parseObject(EntityUtils.toString(response.getEntity()));
String mokaUrl = jsonObject.getJSONObject("data").getString("url");
if (StringUtils.isNotBlank(mokaUrl)) {
EhrFileMessage ehrFileMessageNew = new EhrFileMessage();
ehrFileMessageNew.setEhrUrl(ehrUrl);
ehrFileMessageNew.setMokaUrl(mokaUrl);
ehrFileMessageNew.setFileName(fileName);
ehrFileMessageMapper.insert(ehrFileMessageNew);
}
return mokaUrl;
} else {
log.error("enter MokaProxyService.getMokaUrlByEhrUrl,response:{}", JSON.toJSONString(response));
}
} catch (Exception e) {
log.error("enter MokaProxyService.getMokaUrlByEhrUrl,error:{}", e);
}
return null;
}
public String getMokaToken() {
try {
Object o = crawlerRedissonClient.getMap("ResumeHR:mokahr").get("moka-uid");
if (o != null) {
return o.toString();
} else {
return null;
}
} catch (Exception e) {
log.error("enter MokaProxyService.getMokaToken,error:{}", e);
}
return null;
}
我是和爬虫工程师一起做的,因为没有开放接口,这种请求toc接口是需要登录信息的,这边是我们通过redis对接的,他定时更新cookie;
这里遇到过的问题是,流的处理问题,遇到过文件损坏只支持pdf.但是这种 byte[] bytes = inputStream.readAllBytes();非拼接的方法解决了,还有文件的名字的后缀要规范;
后面的优化是,做了个字典表,防止请求过多,别人还以为是被攻击了呢.
本次redis不变的临时链接redis的示例
@PostConstruct
public void init() {
Config config = new Config();
config.setCodec(StringCodec.INSTANCE);
config.setTransportMode(TransportMode.NIO);
config.useSingleServer().setAddress("redis://xxx:6379").setDatabase(3).setPassword("xxx");
crawlerRedissonClient = Redisson.create(config);
}