javax.imageio.ImageIO Проблема создания ImageInputStream - PullRequest
3 голосов
/ 03 августа 2011

У меня есть сервлет в Tomcat 5.5, который читает локальные изображения, сидящие в папке. Затем изображение отправляется обратно в апплет.

Я получаю это «исключение javax.imageio.IIOException: не удается создать ImageInputStream!» ошибка и не знаю, что ее вызвало.

Кто-нибудь имел эту проблему раньше? Может ли это быть темой в ImageIO? Я не могу воспроизвести эту проблему, поскольку она возникает примерно 3 раза на каждые 1000 запросов.

РЕДАКТИРОВАТЬ: Это код сервлета, который читает изображение. Я просто использую ImageIO.read (File) в его статической форме внутри метода doPost сервлета, как показано ниже:

    doPost(req,resp){
       ...
        BufferedImage image = ImageIO.read(imageFile);
       ...
    }

Вот исходный код для javax.imageio.ImageIO.read (Файл):

    public static BufferedImage read(File input) throws IOException {
    if (input == null) {
        throw new IllegalArgumentException("input == null!");
    }
    if (!input.canRead()) {
        throw new IIOException("Can't read input file!");
    }

    ImageInputStream stream = createImageInputStream(input);
    if (stream == null) {
        throw new IIOException("Can't create an ImageInputStream!");
    }
    BufferedImage bi = read(stream);
    if (bi == null) {
        stream.close();
    }
    return bi;
    }

Ответы [ 3 ]

2 голосов
/ 03 августа 2011

Если единственным функциональным требованием является чтение изображений с локального диска и возврат его без изменений в ответ HTTP с использованием сервлета, тогда не вообще нужен ImageIO,Это только добавляет ненужные накладные расходы и другие проблемы, как у вас сейчас.

Избавьтесь от вещей ImageIO и просто передайте необработанное изображение прямо с диска в ответ HTTP вместе с набором правильных заголовков ответа.Например,

String name = request.getParameter("name");
File file = new File("/path/to/images", name);

response.setContentType(getServletContext().getMimeType(file.getName()));
response.setHeader("Content-Length", String.valueOf(file.length()));
response.setHeader("Content-Disposition", "inline; filename=\"" + file.getName() + "\"");

InputStream input = null;
OutputStream output = null;

try {
    input = new BufferedInputStream(new FileInputStream(file));
    output = new BufferedOutputStream(response.getOutputStream());
    byte[] buffer = new byte[8192];

    for (int length; (length = input.read(buffer)) > 0;) {
        output.write(buffer, 0, length);
    }
} finally {
    if (output != null) try { output.close(); } catch (IOException logOrIgnore) {}
    if (input != null) try { input.close(); } catch (IOException logOrIgnore) {}
}

Вот и все.ImageIO вам нужен только всякий раз, когда вы хотите манипулировать изображением в памяти сервера перед его возвратом, например, изменять его размер, преобразовывать или что-то в этом роде.

Другой, более надежный пример такого сервлета можно найти здесь и более продвинутый здесь .

1 голос
/ 03 августа 2011

Источник, который у меня есть (Java5, но я сомневаюсь, что он сильно изменился), утверждает, что, если не зарегистрировано ни одного поставщика услуг ImageInputStream, метод createImageInputStream возвращает ноль, и таким образом вы получаете это исключение.JavaDoc на IIORegistry.getDefaultInstance(), который используется ImageIO:

Каждая группа ThreadG будет получать свой собственный экземпляр;это позволяет различным апплетам в одном и том же браузере (например) каждому иметь свой собственный реестр.

Таким образом, на самом деле это может быть проблема с многопоточностью, поскольку вы получаете простой новый экземпляр IIORegistry.

Редактировать: копая глубже в источник, я нашел следующее:

Скорее всего, вы получите FileImageInputStream, так как вы передаете файл.Однако, если возникает исключение, поставщик услуг возвращает null.Таким образом, может быть выброшен FileNotFoundException или любой другой IOException, что приведет к тому, что поток не будет создан.

К сожалению, в коде нет регистрации, поэтому вам придется как-то отлаживать.Вероятно, это связано с отсутствием прав доступа к файлу, поврежденным / неполным файлом или отсутствующим файлом.

Вот исходный код Java5 для FileImageInputStreamSpi#createInputStreamInstance()

public ImageInputStream createInputStreamInstance(Object input,
                                                  boolean useCache,
                                                  File cacheDir) {
    if (input instanceof File) {
        try {
            return new FileImageInputStream((File)input);
        } catch (Exception e) {
            return null;
        }
    } else {
        throw new IllegalArgumentException();
    }
}
0 голосов
/ 10 декабря 2013

Где вы используете методы close () при обработке исключений? Потоки должны быть закрыты, когда есть исключения, а также нормальное завершение блока кода.

Симптом звучит так, будто вам не хватает места в куче или когда-нибудь.

Это не ошибки кодирования, на которые указывали другие, поскольку проблема временная.

...