2015-05-01 2 views
0

У меня есть изображение, которое я получаю из URL-адреса, который не имеет расширения (jpg, gif, png и т. Д.).Как получить формат изображения из URL-адреса в Java?

У меня нет проблем с загрузкой изображения.

BufferedImage image = null; 
URL url = new URL(link); 
image = ImageIO.read(url); 

Однако, я хотел знать расширение файла перед сохранением на диск. Я попробовал следующее, и ImageIO.createImageInputStream(image); всегда возвращает null.

ImageInputStream iis = ImageIO.createImageInputStream(image); 
//where image is BufferImage but it is always returning null. 

while (imageReaders.hasNext()) { 
    ImageReader reader = imageReaders.next(); 
    System.out.printf("formatName: %s%n", reader.getFormatName()); 

    return ImageFormatTypes.valueOf(reader.getFormatName()); 
} 

Любой совет будет оценен.

+0

Это 'ImageIO.createImageInputStream (url)' (т. Е. Не 'образ'). Не читайте изображение, которое вам не нужно, если вы хотите сохранить только диск. – haraldK

ответ

4

После создания java.awt.Image нет формата. Это не PNG, это не JPEG, это просто образ Java. Таким образом, вы не можете получить формат изображения из объекта Image.

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

URL url = new URL(link); 
URLConnection conn = url.openConnection(); 
String contentType = conn.getContentType(); 

String suffix = null; 
Iterator<ImageReader> readers = 
    ImageIO.getImageReadersByMIMEType(contentType); 
while (suffix == null && readers.hasNext()) { 
    ImageReaderSpi provider = readers.next().getOriginatingProvider(); 
    if (provider != null) { 
     String[] suffixes = provider.getFileSuffixes(); 
     if (suffixes != null) { 
      suffix = suffixes[0]; 
     } 
    } 
} 

Вы также можете сохранить URL временный файл, так что вы можете использовать Files.probeContentType на нем:

URL url = new URL(link); 
Path imageFile = Files.createTempFile("image", null); 
try (InputStream stream = url.openStream()) { 
    Files.copy(stream, imageFile, StandardCopyOption.REPLACE_EXISTING); 
} 

image = ImageIO.read(imageFile.toFile()); 
String contentType = Files.probeContentType(imageFile); 
Files.delete(imageFile); 

Но вам все равно нужны провайдеры ImageIO, чтобы получить расширение из типа MIME.

+0

Большое спасибо @VGR. Это то, что я искал. Один быстрый вопрос: String contentType = conn.getContentType(); Это уже дает мне изображение/png.Разве это не достаточно, чтобы остановиться на этом этапе? – WowBow

+1

Нет. Подтип (часть после '/') не гарантируется на том же уровне, что и расширение. Рассмотрим «image/jpeg» и «image/svg + xml». – VGR

+0

Кроме того, некоторые серверы относятся к типам контента (то есть неправильно сконфигурированы или полагаются на расширение файла, которое может быть неверным). Таким образом, вы не можете слепо доверять типу контента. Рассмотрение фактической полезной нагрузки, например 'Files.probeContentType (..)', является более безопасным. – haraldK

4

В Java 7+ теперь вы можете просто использовать Files.probeContentType(path).

---------- 
public static String probeContentType(Path path) 
           throws IOException 

Зонды типа содержимого файла.

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

Данный вызов виртуальной машины Java поддерживает общесистемный список детекторов типа файла . Установленные детекторы типа файла загружаются , используя средство загрузки поставщика услуг, определенное классом ServiceLoader . Установленные детекторы типа файла загружаются с помощью загрузчика системного класса. Если загрузчик системного класса не найден , то используется загрузчик класса расширения; Если загрузчик класса расширения не найден, используется загрузчик класса загрузки. Тип файла детекторы обычно устанавливаются путем размещения их в файле JAR по пути класса приложения или в каталоге расширения, файл JAR содержит файл конфигурации поставщика с именем java.nio.file.spi.FileTypeDetector в ресурсе directory META-INF/services, и в файле перечислены одно или несколько полностью определенных имен конкретного подкласса FileTypeDetector, у которых есть нулевой аргумент конструктора аргументов . Если процесс обнаружения или создания экземпляров установленных детекторов типов файлов не выполняется, то неуказанная ошибка составляет . Порядок размещения установленных поставщиков: .

Возвращаемое значение этого метода является строка форма стоимости Multipurpose Internet Mail Extension (MIME) типа содержимого, как это определено RFC 2045: Multipurpose Internet Mail Extensions (MIME) Часть первая: Формат Интернета Органы сообщений. Строка гарантированно будет разборчивой в соответствии с грамматикой в ​​RFC.

+0

Спасибо за ответ, и я догадываюсь, понял. Однако я пытался получить Путь и использовал следующий код. Path path = Paths.get (url.toURI()); Тем не менее, он бросает FileSystemNotFoundException: провайдер «http» не установлен. Правильно ли я получаю объект Path? – WowBow

+0

Приветствую вас, я обновил свой ответ. –

+0

Еще раз спасибо. В какой библиотеке вы используете Path и Paths? Кажется, я не вижу метод Paths.getPath. Только метод Paths.get(). Я вижу пакет java.nio.file для обоих классов. Я использую JDK 1.8 – WowBow