文章目录

          • 一、遇到的问题
          • 二、将jar导入maven仓库
          • 三、android客户端生成base64
          • 四、Java接口base64转文件

一、遇到的问题

1.Java中直接使用spring框架提供的工具包来实现,Web页面生成的Base64正常解码,但是Android客户端生成的Base64解码报错,错误信息为:Illegal base64 character a, data=null]。
spring 原生框架提供jar将base64转图片核心代码如下:

 byte[] bs = Base64Utils.decodeFromString(data);try{    //使用apache提供的工具类操作流FileUtils.writeByteArrayToFile(new File("D:", tempFileName), bs);  }catch(Exception ee){  throw new Exception("上传失败,写入文件失败,"+ee.getMessage());}

2.Android客户端提交的Base64使用BASE64Decoder包生成的图片是破损的,原因是可能是没有拼接前缀data:image/jpeg;base64,或者是上传的过程中数据发生了改变。通过浏览器上http://imgbase64.duoshitong.com/,生成base64如下:

生成图片的base64可知,base6前拼接data:image/jpeg;base64,来标识这个base64应该生成什么类型的文件,所以客户端生成的base64也有拼上这段标识,而后台接口接收到数据时先要截取,根据标识去生成文件。

二、将jar导入maven仓库

找了半天找到BASE64Decoder真是太happy了,然而访问到生成图片的代码时却报classNotFoundException,找不到这个包的类,但包明明已经导入到里面去了,编译能通过,但是运行到对应的类就报错了。原因是:通过右键项目Build Path —>Configure Build Path… —>Add External JARS 这样导入的jar包 只存在工作环境当中,当项目部署到tomcat以后,webapp文件夹下的项目文件夹中并不会存在我们的jar包。解决这个问题的方式有两种方法:
1、在WEB-INF下建一个文件夹 lib,把jar包 copy 进去,这样在部署项目的时候就会将jar也部署进去了。
2、将jar导入maven中,生成对应的pom版本。
将jar导入maven的指令:

./mvn install:install-file -Dfile="/Users/linxz/Desktop/jar/sun.misc.BASE64Decoder.jar" -DgroupId=sun.misc.base64decoder -DartifactId=sun.misc.base64decoder -Dversion=1.0.0 -Dpackaging=jar

如果是windows系统,则不要前面的./。

/Users/linxz/Desktop/jar/sun.misc.BASE64Decoder.jar为jar包的位置,DgroupId为项目组ID,DartifactId为项目ID,我这里皆用包名命名,Dversion为当前生成的版本号。这里就有点像android里生成aar部署到Nexus Maven仓库。Nexus搭建Maven私服

执行指令结果如下则表示打包成功:

[INFO] Scanning for projects...[INFO] [INFO] ------------------< org.apache.maven:standalone-pom >-------------------[INFO] Building Maven Stub Project (No POM) 1[INFO] --------------------------------[ pom ]---------------------------------[INFO] [INFO] --- maven-install-plugin:2.4:install-file (default-cli) @ standalone-pom ---[INFO] Installing /Users/linxz/Desktop/jar/sun.misc.BASE64Decoder.jar to /Users/linxz/java/localmaven/sun/misc/base64decoder/sun.misc.base64decoder/1.0.0/sun.misc.base64decoder-1.0.0.jar[INFO] Installing /var/folders/q9/ysm4v_fx14110jhts8dcw5s00000gn/T/mvninstall3804221028910250225.pom to /Users/linxz/java/localmaven/sun/misc/base64decoder/sun.misc.base64decoder/1.0.0/sun.misc.base64decoder-1.0.0.pom[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time:  0.290 s[INFO] Finished at: 2019-10-12T08:38:08+08:00[INFO] ------------------------------------------------------------------------linxzdeMacBook-Pro:bin linxz$ 

Installing /Users/linxz/Desktop/jar/sun.misc.BASE64Decoder.jar to /Users/linxz/java/localmaven/sun/misc/base64decoder为生成的包在我本地maven的路径,可以去该路径下查看是否真的存在:
这时候我们可以在代码中通过maven的方式导入:

<dependency>    <groupId>sun.misc.base64decoder</groupId>    <artifactId>sun.misc.base64decoder</artifactId>    <version>1.0.0</version></dependency>
三、android客户端生成base64
 public static String getBase64FromFilePath(String path){        InputStream inputStream = null;        byte[] data = null;        try {            inputStream = new FileInputStream(path);            data = new byte[inputStream.available()];            inputStream.read(data);            inputStream.close();        } catch (IOException e) {            e.printStackTrace();        }        // 加密        BASE64Encoder encoder = new BASE64Encoder();        String base64=encoder.encode(data);        base64="data:image/jpeg;base64,"+base64;        return base64;    }
四、Java接口base64转文件

核心代码;

public static boolean base64ToImage(String imgStr,String imgFilePath) {if (StringUtils.isEmpty(imgStr)) return false;File file =new File(imgFilePath);File fileParent=file.getParentFile();if(!fileParent.exists()) {fileParent.mkdirs();}BASE64Decoder decoder = new BASE64Decoder();try {byte[] b = decoder.decodeBuffer(imgStr);for (int i = 0; i < b.length; ++i) {if (b[i] < 0) {// 调整异常数据b[i] += 256;}}OutputStream out = new FileOutputStream(imgFilePath);out.write(b);out.flush();out.close();return true;} catch (Exception e) {e.printStackTrace();return false;}}

将传输过程中发生改变的字符替换回来:

base64=base64.replaceAll(" ","+");base64=base64.replaceAll("[\\s*\t\n\r]", "");

文件路径不存在则创建对应文件夹:

File file =new File(imgFilePath);File fileParent=file.getParentFile();if(!fileParent.exists()) {fileParent.mkdirs();}

我项目中的业务处理方式:验证base64非空->验证用户token->验证当前用户状态时候可用->将传输过程中被修改的base64替换回来->根据拼接的前缀判断当前base64属于什么类型文件->判断生成文件的地址路径是否存在不存在则生成对应的路径文件夹->base64开始转文件。

@Overridepublic LinxzResult upLoadImg(FileParams fileParams) {try {if (StringUtils.isEmpty(fileParams.getBase64())) {return LinxzResult.build(ResponseCodeUtils.CODE_PARAMS_EMPTY, "长传失败,上传图片不能为空");}//校验用户String token = fileParams.getToken();if(StringUtils.isEmpty(token)){return LinxzResult.build(ResponseCodeUtils.CODE_PERMISSION_ERRO, "token错误");}String userId=TokenUtils.getUserId(token);BaseUser user=baseUserMapper.selectByUserId(userId);if(user==null || !token.equals(user.getToken())){return LinxzResult.build(ResponseCodeUtils.CODE_PERMISSION_ERRO, "token错误");}if(!UserConfig.USER_STATUS_NORMAL.equals(user.getStattus())){return LinxzResult.build(ResponseCodeUtils.CODE_PERMISSION_ERRO, "用户异常");}String base64=fileParams.getBase64();base64=base64.replaceAll(" ","+");base64=base64.replaceAll("[\\s*\t\n\r]", "");System.out.println("上传文件的数据:" + base64);String dataPrix = "";String data = "";String[] d = base64.split("base64,");if (d != null && d.length == 2) {dataPrix = d[0];data = d[1];} else { return LinxzResult.build(ResponseCodeUtils.CODE_UNKNOWED_ERRO, "上传失败,数据不合法");}String suffix = "";if ("data:image/jpeg;".equalsIgnoreCase(dataPrix)) {// data:image/jpeg;base64,base64编码的jpeg图片数据suffix = ".jpg";} else if ("data:image/x-icon;".equalsIgnoreCase(dataPrix)) {// data:image/x-icon;base64,base64编码的icon图片数据suffix = ".ico";} else if ("data:image/gif;".equalsIgnoreCase(dataPrix)) {// data:image/gif;base64,base64编码的gif图片数据suffix = ".gif";} else if ("data:image/png;".equalsIgnoreCase(dataPrix)) {// data:image/png;base64,base64编码的png图片数据suffix = ".png";} else { return LinxzResult.build(ResponseCodeUtils.CODE_UNKNOWED_ERRO, "上传图片格式不合法");}String tempFileName = getRandomFileName() + suffix;String homePath = "/Users/linxz/Pictures/streamlet/";String folderName="";if (!StringUtils.isEmpty(fileParams.getFolderName())) {folderName = fileParams.getFolderName();}homePath = homePath+folderName+"/"+user.getUserId()+"/"+tempFileName;boolean success=Base64Util.base64ToImage(data, homePath);if(success) {System.out.println("生成文件名为:" + homePath);return LinxzResult.build(ResponseCodeUtils.CODE_SUCCESS, "长传成功", folderName + "/" + user.getUserId()+"/"+tempFileName);}else { return LinxzResult.build(ResponseCodeUtils.CODE_UNKNOWED_ERRO, "上传失败,写入文件失败");}} catch (Exception e) {return LinxzResult.build(ResponseCodeUtils.CODE_UNKNOWED_ERRO, "长传失败" + e.getMessage());}}

之前一直觉得,开发接口之后postman请求没问题就证明接口是可用的,剩下的就是客户端的问题,这个图片上传使用Srping的包,postman请求网页生成的base64没问题,可是android原生bas4工具类生成的base64就是死活解码失败,改变了我接口对接的一些看法。

更多相关文章

  1. SpringBoot 2.0 中 HikariCP 数据库连接池原理解析
  2. 一句话锁定MySQL数据占用元凶
  3. android 模拟器手机如何添加文件到sd卡?
  4. error: Error parsing XML: unbound prefix 与 error: Invalid s
  5. Android(安卓)ListView动画(逐行显示动画效果)
  6. Android技术周报_W2_2017年01月15日
  7. Android(安卓)studio的那些坑- so文件添加的正确位置
  8. Android(安卓)ADB详细介绍及用法
  9. Android应用程序四大组件之使用AIDL如何实现跨进程调用Service

随机推荐

  1. Android(安卓)LayoutEditor使Eclipse自动
  2. Android(安卓)中使用OpenGL ES进行2D开发
  3. Android应用实例之----基于Service与Cont
  4. Android(安卓)动画效果 --Animation 动画
  5. 系出名门Android(4) - 活动(Activity),
  6. Android(安卓)P按键静音流程
  7. android开发中@+id/和android:id用法的区
  8. Android几种FrameWork(Manager)的用法
  9. Android之SharedPreferences详解与原理分
  10. Android百度地图(一):百度地图定位sdk 类