Java - кодирование изображений в XML
Я думал, что найти решение этой проблемы относительно легко, но здесь я призываю помощь богов, чтобы вытащить меня из этой головоломки.
Итак, у меня есть изображение, и я хочу сохранить его в XML-документе с помощью Java. Я уже достиг этого в VisualBasic, сохраняя изображение в потоке, преобразовывая поток в массив, а затем класс VB xml смог кодировать массив как строку base64. Но, после нескольких часов чистки сети для эквивалентного решения на Java, я вернулся с пустыми руками. Единственный успех у меня был:
import it.sauronsoftware.base64.*;
import java.awt.image.BufferedImage;
import org.w3c.dom.*;
...
BufferedImage img;
Element node;
...
java.io.ByteArrayOutputStream os = new java.io.ByteArrayOutputStream();
ImageIO.write(img, "png", os);
byte[] array = Base64.encode(os.toByteArray());
String ss = arrayToString(array, ",");
node.setTextContent(ss);
...
private static String arrayToString(byte[] a, String separator) {
StringBuffer result = new StringBuffer();
if (a.length > 0) {
result.append(a[0]);
for (int i=1; i<a.length; i++) {
result.append(separator);
result.append(a[i]);
}
}
return result.toString();
}
Я думаю, что это нормально, но изменение процесса, чтобы вернуть его к изображению при загрузке XML файла оказалось невозможным. Если у кого-то есть лучший способ кодировать/декодировать изображение в XML файле, сделайте шаг вперед, даже если это просто ссылка на другой поток, который будет в порядке.
Приветствия заранее,
шумихи.
Ответы
Ответ 1
Я сделал что-то подобное (кодирование и декодирование в Base64), и он работал как шарм. Здесь я думаю, что вы должны сделать, используя класс Base64
из проекта Apache Commons:
// ENCODING
BufferedImage img = ImageIO.read(new File("image.png"));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(img, "png", baos);
baos.flush();
String encodedImage = Base64.encodeToString(baos.toByteArray());
baos.close(); // should be inside a finally block
node.setTextContent(encodedImage); // store it inside node
// DECODING
String encodedImage = node.getTextContent();
byte[] bytes = Base64.decode(encodedImage);
BufferedImage image = ImageIO.read(new ByteArrayInputStream(bytes));
Надеюсь, что это поможет.
Ответ 2
Apache Commons имеет класс Base64, который должен быть вам полезен:
Оттуда вы можете просто записать байты (они уже в читаемом формате)
Ответ 3
После получения массива байтов
byte[] array = Base64.encode(os.toByteArray());
используйте закодированную строку:
String encodedImg = new String( array, "utf-8");
Затем вы можете делать забавные вещи в своем xml, например
<binImg string-encoding="utf-8" bin-encoding="base64" img-type="png"><![CDATA[ encodedIImg here ]]></binImg>
Ответ 4
С помощью Java 6 вы можете использовать DatatypeConverter для преобразования байтового массива в строку Base64:
byte[] imageData = ...
String base64String = DatatypeConverter.printBase64Binary(imageData);
И для его возврата:
String base64String = ...
byte[] imageData = DatatypeConverter.parseBase64Binary(base64String);
Ответ 5
Ваш метод arrayToString()
довольно странный (какая точка этого разделителя?). Почему бы просто не сказать
String s = new String(array, "US-ASCII");
Обратная операция
byte[] array = s.getBytes("US-ASCII");
Используйте кодировку ASCII, которая должна быть достаточной при работе с закодированными Base64 данными. Кроме того, я бы предпочел кодировщик Base64 от авторитетного источника, такого как Apache Commons.
Ответ 6
Для этого вам не нужно изобретать свой собственный тип данных XML. XML-схема определяет стандартные двоичные типы данных, такие как base64Binary, что именно то, что вы пытаетесь сделать.
Как только вы используете стандартные типы, он может быть автоматически преобразован в двоичный код с помощью некоторых парсеров (например, XMLBeans). Если ваш парсер не справляется с этим, вы можете найти классы для base64Binary во многих местах, поскольку тип данных широко используется в SOAP, XMLSec и т.д.
Ответ 7
Самая простая реализация, которую я смог сделать, таков, как показано ниже. И это от передачи Server to Server XML, содержащей двоичные данные Base64, из библиотеки Apache Codec:
- Чтение двоичных данных из БД и создание XML
Blob blobData = oRs.getBlob("ClassByteCode");
byte[] bData = blobData.getBytes(1, (int)blobData.length());
bData = Base64.encodeBase64(bData);
String strClassByteCode = new String(bData,"US-ASCII");
- на запрашивающем сервере прочитайте тег и сохраните его в БД
byte[] bData = strClassByteCode.getBytes("US-ASCII");
bData = Base64.decodeBase64(bData);
oPrStmt.setBytes( ++nParam, bData );
легко, как может быть..
Я все еще работаю над реализацией потоковой передачи XML, поскольку он генерируется с первого сервера, на котором создается XML, и передает его в объект ответа, поэтому нужно следить, когда XML с двоичными данными слишком велик.
Ответ 8
Основная проблема заключается в том, что вы не можете иметь произвольный поток в XML-документе, поэтому вам нужно каким-то образом закодировать его. Частая схема кодирования - BASE64, но любой будет делать, пока получатель знает об этом.
Ответ 9
Я знаю, что вопрос заключался в том, как кодировать изображение через XML, но также можно просто передавать байты через HTTP-запрос GET вместо использования XML и кодирования изображения. Обратите внимание, что вход является FileInputStream
.
Код сервера:
File f = new File(uri_string);
FileInputStream input = new FileInputStream(f);
OutputStream output = exchange.getResponseBody();
int c = 0;
while ((c = input.read()) != -1) {
output.write(c); //writes each byte to the exchange.getResponseBody();
}
result = new DownloadFileResult(int_list);
if (input != null) {input.close();}
if (output != null){ output.close();}
Код клиента:
InputStream input = connection.getInputStream();
List<Integer> l = new ArrayList<>();
int b = 0;
while((b = input.read()) != -1){
l.add(b);//you can do what you wish with this list of ints ie- write them to a file. see code below.
}
Вот как вы могли бы написать список Integer в файл:
FileOutputStream out = new FileOutputStream("path/to/file.png");
for(int i : result_bytes_list){
out.write(i);
}
out.close();
Ответ 10
node.setTextContent( base64.encodeAsString( fileBytes ) )
используя org.apache.commons.codec.binary.Base64