尝试从String转换为PNG时由ZipException引起的Java IIOException

时间:2015-02-20 16:42:05

标签: java servlets png bufferedimage javax.imageio

我的Java Servlet有一个来自客户端的字符串(我知道他实际上是在发送一个PNG作为参数,在一个请求中使用contentType = application/x-www-form-urlencoded),我试图将其转换回文件并保存。这是我的代码(基于this):

byte[] data = org.apache.commons.codec.binary.Base64.decodeBase64(request.getParameter("image").getBytes());
String filename = request.getParameter("filename");

try{
    java.awt.image.BufferedImage image = javax.imageio.ImageIO.read(new ByteArrayInputStream(data));
    javax.imageio.ImageIO.write(image, "png", new File(getUploadFolder() + filename + ".png"));
}catch(Exception e){
    System.out.println("Exception saving image: " + e.getMessage());
    e.printStackTrace();
}

这是我的错误堆栈跟踪:

Exception saving image: Error reading PNG image data
javax.imageio.IIOException: Error reading PNG image data
    at com.sun.imageio.plugins.png.PNGImageReader.readImage(PNGImageReader.java:1308)
    at com.sun.imageio.plugins.png.PNGImageReader.read(PNGImageReader.java:1577)
    at javax.imageio.ImageIO.read(ImageIO.java:1448)
    at javax.imageio.ImageIO.read(ImageIO.java:1352)
    at com.mypackage.servlet.UploadServlet.doPost(UploadServlet.java:113)
Caused by: java.util.zip.ZipException: invalid code lengths set
    at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:164)
    at java.io.BufferedInputStream.fill(BufferedInputStream.java:235)
    at java.io.BufferedInputStream.read(BufferedInputStream.java:254)
    at java.io.FilterInputStream.read(FilterInputStream.java:83)
    at com.sun.imageio.plugins.png.PNGImageReader.decodePass(PNGImageReader.java:1085)
    at com.sun.imageio.plugins.png.PNGImageReader.decodeImage(PNGImageReader.java:1196)
    at com.sun.imageio.plugins.png.PNGImageReader.readImage(PNGImageReader.java:1301)
    ... 4 more

查看InflaterInputStream类代码,我发现它实际上是一个DataFormatException:

public int read(byte[] b, int off, int len) throws IOException {
    ensureOpen();
    if (b == null) {
        throw new NullPointerException();
    } else if (off < 0 || len < 0 || len > b.length - off) {
        throw new IndexOutOfBoundsException();
    } else if (len == 0) {
        return 0;
    }
    try {
        int n;
        while ((n = inf.inflate(b, off, len)) == 0) {
            if (inf.finished() || inf.needsDictionary()) {
                reachEOF = true;
                return -1;
            }
            if (inf.needsInput()) {
                fill();
            }
        }
        return n;
    } catch (DataFormatException e) {
        String s = e.getMessage();
        throw new ZipException(s != null ? s : "Invalid ZLIB data format");
    }
}

但这并不是那么具有启发性。

1 个答案:

答案 0 :(得分:1)

正如@leonbloy所说,没有必要解码然后重新编码数据。

如果你确定PNG文件是好*,你可以简单地将数据写入文件,如下所示,你应该完成。

byte[] data = org.apache.commons.codec.binary.Base64.decodeBase64(request.getParameter("image").getBytes());
String filename = request.getParameter("filename");

OutputStream output = new FileOutputStream(new File(getUploadFolder() + filename + ".png"));

try {
    output.write(data);
}
finally {
    output.close();
}

*)到目前为止提供的证据表明不然,您使用的代码应该可以工作(即使它浪费了CPU周期)。看到产生您看到的异常的数据样本将非常有趣,以找出异常的原因。