Java 尝试从 String 转换为 PNG 时由 ZipException 引起的 IIOException
Java IIOException caused by ZipException while trying to convert from String to PNG
我的 Java Servlet 有一个来自客户端的字符串(我所知道的是他实际上是在 contentType = application/x-www-form-urlencoded
的请求中向我发送一个 PNG 作为参数),我正在尝试将其转换回文件并保存。这是我的代码(基于 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 class 代码,我发现它实际上是一个 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");
}
}
但这并没有那么有启发性。
正如@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 周期)。如果能看到产生您看到的异常的数据样本,找出异常的原因,那将是非常有趣的。
我的 Java Servlet 有一个来自客户端的字符串(我所知道的是他实际上是在 contentType = application/x-www-form-urlencoded
的请求中向我发送一个 PNG 作为参数),我正在尝试将其转换回文件并保存。这是我的代码(基于 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 class 代码,我发现它实际上是一个 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");
}
}
但这并没有那么有启发性。
正如@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 周期)。如果能看到产生您看到的异常的数据样本,找出异常的原因,那将是非常有趣的。