Base 64 编码的 QRGen QR 码无法解码

huangapple go评论83阅读模式
英文:

Base 64 Encoded QRGen QR code can't be decoded

问题

我试图使用QRGen生成一个QR码,将其编码为Base64,并将其作为图像插入到HTML字符串中。稍后,HTML字符串被解码以在JEditorPane中显示(然后发送到打印机)。为此,扩展了ImageView类并使用了自定义的View工厂。这一切都运行良好... 有时候。这完全取决于输入的字符串。有些字符串没有问题,而其他一些字符串会导致解码过程失败,并显示错误java.lang.IllegalArgumentException: 输入字节数组具有错误的4字节结尾单元

这是编码过程:

 public BufferedImage generateQRCodeImage(String barcodeText) throws Exception {
        ByteArrayOutputStream stream = QRCode.from(barcodeText).to(ImageType.PNG).stream();
        ByteArrayInputStream bis = new ByteArrayInputStream(stream.toByteArray());
        return ImageIO.read(bis);
    }

    public static String encodeToString(BufferedImage image, String type) {
        String imageString = null;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try {
            ImageIO.write(image, type, bos);
            byte[] imageBytes = bos.toByteArray();
            Base64.Encoder encoder = Base64.getEncoder();
            imageString = encoder.encodeToString(imageBytes);
            bos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return imageString;
    }

解码过程:

        

        private Image loadImage() {
            String b64 = getBASE64Image();
            BufferedImage newImage = null;
            ByteArrayInputStream bais = null;
            try {
                bais = new ByteArrayInputStream(Base64.getDecoder().decode(b64.getBytes())); //fails here
                newImage = ImageIO.read(bais);
            } catch (Throwable ex) {
                ex.printStackTrace();
            }
            return newImage;
        }

        @Override
        public URL getImageURL() {
            String src = (String) getElement().getAttributes().getAttribute(HTML.Attribute.SRC);
            if (isBase64Encoded(src)) {

                this.url = BASE64ImageView.class.getProtectionDomain()
                        .getCodeSource().getLocation();

                return this.url;
            }
            return super.getImageURL();
        }

        private boolean isBase64Encoded(String src) {
            return src != null && src.contains("base64,");
        }

        private String getBASE64Image() {
            String src = (String) getElement().getAttributes().getAttribute(HTML.Attribute.SRC);
            if (!isBase64Encoded(src)) {
                return null;
            }
            return src.substring(src.indexOf("base64,") + 7, src.length() - 1);
        }

这是出问题的QR码:

<img width='30' height='30' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAH0AAAB9AQAAAACn+1GIAAAApklEQVR4Xu2UMQ4EMQgD/QP+/0vK6zjsvayUMmavWxQpMAUBkwS12wcveAAkgNSCD3rR5Lkgoai3GUCMgWqbAEYR3HxAkZlzU/0MyBisYRsgI1ERFfcpBpA+ze6k56Cj7KTdXNigFWZvSOpsgqLfd18i2aAukXh9TXBNmdWt5gzA/oqzWkkN8HtA7G8CNOwYAiZt3wZixUfkA32OHNQq7Bxs9oI/gC/9fV8AVCkPjQAAAABJRU5ErkJggg=='/>

我确实在浏览器(Chrome)中打开了上面的QR码,它确实能正常工作,这明确指出了解码过程有问题,而不是编码过程。

英文:

Im trying to generate a QR code using QRGen, encode it in Base64 and insert it as an image in an HTML string. Later, the HTML string is decoded to be displayed in a JEditorPane (and then sent to a printer). To this end, the ImageView class is extended and a custom View factory is used. This all works fine... sometimes. It completely depends on the input string. Some strings work without issue, others fail cause the decode process to fail with the error java.lang.IllegalArgumentException: Input byte array has wrong 4-byte ending unit.

Here is the encode process:

 public BufferedImage generateQRCodeImage(String barcodeText) throws Exception {
ByteArrayOutputStream stream = QRCode.from(barcodeText).to(ImageType.PNG).stream();
ByteArrayInputStream bis = new ByteArrayInputStream(stream.toByteArray());
return ImageIO.read(bis);
}
public static String encodeToString(BufferedImage image, String type) {
String imageString = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
ImageIO.write(image, type, bos);
byte[] imageBytes = bos.toByteArray();
Base64.Encoder encoder = Base64.getEncoder();
imageString = encoder.encodeToString(imageBytes);
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
return imageString;
}

and the decode process:

        
private Image loadImage() {
String b64 = getBASE64Image();
BufferedImage newImage = null;
ByteArrayInputStream bais = null;
try {
bais = new ByteArrayInputStream(Base64.getDecoder().decode(b64.getBytes())); //fails here
newImage = ImageIO.read(bais);
} catch (Throwable ex) {
ex.printStackTrace();
}
return newImage;
}
@Override
public URL getImageURL() {
String src = (String) getElement().getAttributes().getAttribute(HTML.Attribute.SRC);
if (isBase64Encoded(src)) {
this.url = BASE64ImageView.class.getProtectionDomain()
.getCodeSource().getLocation();
return this.url;
}
return super.getImageURL();
}
private boolean isBase64Encoded(String src) {
return src != null &amp;&amp; src.contains(&quot;base64,&quot;);
}
private String getBASE64Image() {
String src = (String) getElement().getAttributes().getAttribute(HTML.Attribute.SRC);
if (!isBase64Encoded(src)) {
return null;
}
return src.substring(src.indexOf(&quot;base64,&quot;) + 7, src.length() - 1);
}

And here is the QR code in question that fails to decode.

&lt;img width=&#39;30&#39; height=&#39;30&#39; src=&#39;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAH0AAAB9AQAAAACn+1GIAAAApklEQVR4Xu2UMQ4EMQgD/QP+/0vK6zjsvayUMmavWxQpMAUBkwS12wcveAAkgNSCD3rR5Lkgoai3GUCMgWqbAEYR3HxAkZlzU/0MyBisYRsgI1ERFfcpBpA+ze6k56Cj7KTdXNigFWZvSOpsgqLfd18i2aAukXh9TXBNmdWt5gzA/oqzWkkN8HtA7G8CNOwYAiZt3wZixUfkA32OHNQq7Bxs9oI/gC/9fV8AVCkPjQAAAABJRU5ErkJggg==&#39;/&gt;

I did open the above QR in a browser (Chrome) and it does work, which definitely points to something being wrong in the decode process and not the encode process.

答案1

得分: 0

找到问题所在。在getBASE64Image()函数中,我有以下代码:

private String getBASE64Image() {
    String src = (String) getElement().getAttributes().getAttribute(HTML.Attribute.SRC);
    if (!isBase64Encoded(src)) {
        return null;
    }
    return src.substring(src.indexOf("base64,") + 7, src.length() - 1);
}

substring调用中的"-1"是导致问题的原因。不太清楚为什么这样做只有时候有效,但是删除它似乎已经解决了这个问题。

英文:

Found the issue. In getBASE64Image(), I have

private String getBASE64Image() {
String src = (String) getElement().getAttributes().getAttribute(HTML.Attribute.SRC);
if (!isBase64Encoded(src)) {
return null;
}
return src.substring(src.indexOf(&quot;base64,&quot;) + 7, src.length() - 1);
}

The "-1" in the substring call was the cause of my problems. Not sure why this would work only sometimes, but removing seems to have fixed the problem.

huangapple
  • 本文由 发表于 2020年10月22日 03:12:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/64470222.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定