欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

base64转图片问题javax.imageio.IIOException: Invalid JPEG file structure: two SOI markers

程序员文章站 2022-04-28 21:27:52
...
报错信息:
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转图片问题javax.imageio.IIOException: Invalid JPEG file structure: two SOI markers

字符串中的加号“+”被替换成了空格“ ”

找到了问题,自然有了解决方案:重新替换过来即可。由于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天才想起来写博客,所以原文链接找不到了,只留下截图,若原作者看到请指出来源,认为侵权的请联系我删除

base64转图片问题javax.imageio.IIOException: Invalid JPEG file structure: two SOI markers

但是用这个方法仍然没有解决数据丢失的问题,这个事情告一段落吧,希望有知道原因的大神分享一下。