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