base64转图片问题javax.imageio.IIOException: Invalid JPEG file structure: two SOI markers
javax.imageio.IIOException: Invalid JPEG file structure: two SOI markers
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readImage(Native Method)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:1231)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:1034)
at javax.imageio.ImageIO.read(ImageIO.java:1448)
at javax.imageio.ImageIO.read(ImageIO.java:1308)
at com.hlxd.base.BaseController.uploadCaseMainPicImgByBase64(BaseController.java:272)
at com.hlxd.controller.ws.AppDesignerControllerImpl.updateMyInfo(AppDesignerControllerImpl.java:188)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.j
ava:104)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.
java:749)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java
:689)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:650)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at com.hlxd.base.CorsFilter.doFilter(CorsFilter.java:37)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383)
at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:123)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:625)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
检查发现前端传过来的base64字符串在传输过程中被改变了
这是后端接收到的字符串:
data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAoHBwgHBgoICAgLCgoLDhgQDg0NDh0VFhEYIx8lJCIfIiEmKzcvJik0KSEiMEExNDk7Pj4 JS5ESUM8SDc9Pjv/2wBDAQoLCw4NDhwQEBw7KCIoOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozv/wAARCAB8AHwDASIAAhEBAxEB/8QAGgABAAMBAQEAAAAAAAAAAAAAAAQFBgMBAv/EADwQAAEDAwMCAwYCBQ0AAAAAAAEAAgMEBREGEiETMUFRYRQVMnGBsSKRI0KhssEHJCUzNTZDYnOCo9Hw/8QAGwEBAAMBAQEBAAAAAAAAAAAAAAMEBQECBgf/xAAqEQACAgEDAwIFBQAAAAAAAAAAAQIDERIhMQQiQVFhExQjgZEyM3HB4f/aAAwDAQACEQMRAD8A3aIi/NDaCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCKjsuo5LxHPI2gcxsAyQ2QOLj5DIC723Udvuc3s8b3xT8/opW4PCmlRZHOVwWJ9NbBtOPHPsWqIo09xpKWpjp55hHJL8AcMA/XsolFvZEMYuTwiSiz9w1O jvgtjKNsrnlrWvMu3l30Kuqqc01FLUFuTHGX7c98DOMqSVU44yueCWdFkNOpfq4OyKj0/qKS yTD2NsLYQNzuruJJz4Y9FeAg9jlebK5VvTI821Tqk4TW4RU9/v4sYgJp t1i79fbjGPT1VhQ1RraOOoML4eoAQ15GcfQrrrkoqbWzDpnGtWNbMkIqG4apit9493upXy8AbmHncfDH5eKvWOL2NcWlpIzg9wk65QSclyJ0zrScls D1EBBzgg aKMjCIiHDD6RutLa7fUvqzI1jpB IRucO3mBhdaiG21l1ZeqN9U4NcHmOKleRI4f5sYChCAxaCdIRjrVG4fmB/BR33cwaYpbfTvLZXvc95aeQA7j9v2W5oUpucec4Z9TKl2WSsre7lpfpjG5qbJfLhVVBguFunh3OJjkETg0DyPH7U1db46 hizUw07435DpnbQQRyPspWnYbhFbWOuFQZHvaCGubywep8VBuek4rje21jpNsDxmVg7kjtj5/wDu6pKVcb8p4wZMZVw6lyzpx6bmZfIyXU1D0ajrhjoWdXHxEYBK2Fyp7oLZUmSvgcwROJaKYjIx571nbhROZrSnjpqciON0RAY3hoGFZ 857jXT2d9a2CR26Pa l7j0If5KzZ3aZLhblzqe/wCHKHCSfGdvwVmi4auYVwpaplOcMDi6Lfn4u3IwtBZbHV2md73XQ1EUhLnxuixl3nnPdRbfpastkNRHS3VrPaAA53s/Ixnsd3qpmnaN9FA Nt0bXQtcWhoZgxuHcZyfyUN9ilqcJLH8f4QdZfG2U51yWHjbHt64KnUtNJeNSUdujcAGR7nEjIaCefsFzvNVeqe701JT1jXujZ1D049jGjn4uTxgKdfKOSit10uXULamZzA1zCQWMDgAAfuvjTtILnp97qmWR0k78SvLiXPaDw3PkvcJxValylsSQsUaY2PDjHbGPL3bKyy26uvVzlvT3xxbX7mOewvBPbgZHZWVpvVdeZ3Q09UGFrcuc6kGB/yKv0vX3OoqJbfDVsZFGwuaJIt MEDA5HmoelzVNFfJS1DYXRw7iXR7s9 3IwppxbUs42xj2LN9Tm7NWO3GPZP7GntOn6y2Vrqj3sZmSOLpY3RfGfPvwVfLK6Jr66sZUMqJ rFFjG/lwJ9fJapZnU6lZiTyzG62NkbnGx5aCIirlMy2q2U1v01FQMeAQWtY0nlwHcqBpDTzKnbc6nDo2u/RM8yPEqXeNLzy26aqfM tuBwc9gBnkNHyVbbblqG1UbaSC1vdG0kgvp3k88 C14ZlS41y3yfRVyb6Rwpn3N7 PwbiWrjhqoKZ2d8 7bj0GSo1XTPaXzvu09PF3IzGGt/NqzNHU6hrr/S1U9A5gj/CQY3Ma1p I8 K1MlooZ5utPAJn5z lcXgfIE4CpygqZLL/sy7alRJJvO3jcyN11G6B/St1zqp355keGBv0/Dkru60XGh/py4VDjO0jqdFrS5rMYzyMZHH0zyq/UkNZU380sVFjotDYmRNzlncFamkiv1bHi4OpqWMjBjYzc5w8uSR91dnJQhFxws8mna400wcMLPPrgprldppGiC019dXSPH4ixrdrQfkzOfsrTTdjFAPasVdO94w GWRrmu9eB/0VVXGw3OyVDquyySGE8ljOS36frBWWmbrd7pudUshEEZ2uftIcT5eS8W/s/Tax59SG K XzS1p8 v3RK1b/dqr/2fvBQ9JVUFPYYmSyta SRwY3xcc AUjWEVVLYpG0/LdwMrQMkt9PrhcdLad93QCrqm/wA6kHAP G0 HzUMHBdN3PyQwda6BqT31cfYpdF/27U/6Lv3go2maiGCG5daVke Ahu5wGTzwtbaNN01nqJamOWSSWRpad2MAZysxpCiZcPeFNLnZJEASPDlWviwmpy8bF/5iu1XTXHaWH8n/wDV13zZ/FbBQLTZqWzQOiptx3nLnPOSVPWb1E1OxyXBjdZdG6 U48MIiKAqBMIiHQiIgPNoyXYGcd16iIAgGOwwiIAiIgC IoIoGbIY2Rt8mNAC 0TLGXjAREQ4EREAREQBERAEREAREQBERAEREAREQBERAEREAREQBERAEREAREQBERAEREAREQH/2Q==
这是前端浏览器下看到的字符串:
data:image/jpeg;base64,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
仔细检查发现
字符串中的加号“+”被替换成了空格“ ”
找到了问题,自然有了解决方案:重新替换过来即可。由于base64字符串都不会有空格,所以替换回去不会有问题。
/**
* 上传案例主图
* @param imgStr
* @return
* @author heh
* @date Oct 12, 2017
* @modifytime 2017-12-14
*/
protected String uploadCaseMainPicImgByBase64(String imgStr){
if(imgStr.length() > 50) {
imgStr = imgStr.substring(imgStr.indexOf("base64,")+7).replace(" ", "+");
String imgs = "";
try {
if(null==imgStr){
return imgs;
}
String base64str = imgStr;
BASE64Decoder decoder = new BASE64Decoder();
//Base64解码
byte[] b = decoder.decodeBuffer(base64str);
for(int j=0;j<b.length;++j) {
if(b[j]<0){//调整异常数据
b[j]+=256;
}
}
//生成jpeg图片
Map paramMap = SysCache.getSysCaches("commonParamPro");
String _path = (String) paramMap.get("imgUpload.path");
Long timestamp = System.currentTimeMillis();
String imgName = timestamp + ".jpg";
String imgFilePath = _path + "/" + imgName;//新生成的图片
OutputStream out = new FileOutputStream(imgFilePath);
out.write(b);
out.flush();
out.close();
imgs = "/img/upload/" + imgName;
// 生成app专用图片
String imgFilePath_app = _path + "/" + timestamp + "_app.jpg";
File f = new File(imgFilePath);
BufferedImage bufferedImage = ImageIO.read(f);
Integer width = bufferedImage.getWidth();
Integer height = bufferedImage.getHeight();
if(width > 2000){
Float tmp = 2000/Float.valueOf(width);
Float newHeight = Float.valueOf(height)*tmp;
height = newHeight.intValue();
width = 2000;
}
Thumbnails.of(f).forceSize(width/2, height/2).outputFormat("jpg").toFile(imgFilePath_app);
}
catch (Exception e) {
e.printStackTrace();
}
return imgs;
}else {
return imgStr;
}
}
问题是解决了,但是具体原因还没有发现,为什么会在传输的过程中数据丢失。
网上找了一下解决方案,有这样做的(因为隔了N天才想起来写博客,所以原文链接找不到了,只留下截图,若原作者看到请指出来源,认为侵权的请联系我删除)
但是用这个方法仍然没有解决数据丢失的问题,这个事情告一段落吧,希望有知道原因的大神分享一下。