2015-02-20 4 views
0

В моем сервлете Java есть строка, исходящая от клиента (все, что я знаю, это то, что он фактически отправляет мне PNG в качестве параметра в запрос с contentType = application/x-www-form-urlencoded) , и я пытаюсь преобразовать его обратно в файл и сохранить его. Вот мой код (на основе this):Java IIOException, вызванное ZipException при попытке конвертировать из String в PNG

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(); 
} 

А вот моя ошибка StackTrace:

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"); 
    } 
} 

Но на самом деле это не так поучительно.

+0

Вы уверены, что он отправляет действительный файл png? – afzalex

+0

Недавно мы сменили сервер с php на сервлеты/jsp, и раньше они отправляли изображения. – ocramot

+2

Если поток байтов, который вы получаете в 'data', является только PNG-файлом, почему вы его декодируете и перекодируете? Вы могли бы просто сохранить его как файл с расширением .png, и вы должны это сделать, нет? – leonbloy

ответ

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(); 
} 

*) Доказательства, представленные до сих пор говорят об обратном, а код, который вы использовали должен работать (даже если это пустая трата циклов центрального процессора). Было бы очень интересно увидеть образец данных, создающих исключение, которое вы видите, чтобы выяснить причину исключения.

+1

Наконец-то мне удалось получить код клиента, и теперь я получаю изображение как «multipart/form-data», как и должно быть, и теперь я уверен, что png хорош. Однако ваш код верен, и спасибо за то, что вы заметили ненужное перекодирование, поэтому я считаю правильный ответ правильным. – ocramot