前言
公司存在多个项目需要使用 kk 的预览服务,但是使用的版本并不一致。部分项目因为上线时间较早,所以使用的是旧版的 kk,比如 2.x。kk 本身也在迭代,所以造成了旧项目在接入新版 kk 服务的时候产生了不兼容的现象。
问题原因
部分项目使用的 2.x 版本 kk 是使用的未 base64 编码的 url,而新版 4.0.0 的则是需要传入编码过的 url 才可以支持预览。新版的 kk 在很早前因为需要彻底解决各种奇葩文件名预览问题,所以 url 采用了 base64+urlencode 双编码。
旧项目当中在接入预览服务时需要传入明文地址,这样就导致预览服务无法使用了。
解决方案
可选的处理办法有两种。
额外传参
一个是增加一个参数告诉预览服务是使用的明文地址,预览服务需要根据额外的参数做兼容处理,初始版本是使用的这种办法,保证服务可用。
这种方法的缺点就是预览服务和使用方需要同时修改代码,但是使用方的修改量较小。
不额外传参
利用 url 本身的内容是否是经过 base64 编码的来区分处理。
好处就是不需要接入方做任何额外的改动,用户感觉不到变化。
修改方法
修改的关键就是判断字符串是否是经过 base64 加密的:将字符串解密后再将解密字符串加密回去与原来的值做比较,如果相同就是 base64。网上存在较多文章但是并不适用,所以这里结合 kk 的实际情况需要修改判断方法。
- 修改工具类文件
server/src/main/java/cn/keking/utils/WebUtils.java
,在后面追加判断 url 是否 base64 编码的方法。
/**
* url是否base64编码
*
* @param str str
* @return boolean
*/
public static boolean isBase64(String str) {
// 将字符串解密后再将解密字符串加密回去与原来的值做比较 如果相同就是base64
try {
String decodeStr = new String(Base64Utils.decodeFromString(str), StandardCharsets.UTF_8);
return str.equals(Base64Utils.encodeToString(decodeStr.getBytes(StandardCharsets.UTF_8)));
} catch (Exception e) {
return false;
}
}
- 修改过滤器
server/src/main/java/cn/keking/web/filter/TrustHostFilter.java
,追加对 url 参数的判断。
在 doFilter
方法中处理:
if (WebUtils.isBase64(url)) {
url = new String(Base64Utils.decodeFromString(url), StandardCharsets.UTF_8);
}
- 修改主程序
server/src/main/java/cn/keking/web/controller/OnlinePreviewController.java
,在onlinePreview
方法中追加判断。
if (WebUtils.isBase64(url)){
fileUrl = new String(Base64.decodeBase64(url), StandardCharsets.UTF_8);
} else {
fileUrl = url;
}
然后重新编译项目就可以使用了。
总结
本次修改是为了向下兼容非 base64 编码的文件地址,所以是服务降级,有可能出现奇葩文件名预览问题。因为需要统一服务的原因所以才会产生这个临时修改方案,总体还是建议在合适时间适配到新版的 kk 服务,保证用户体验。