Как программно написать nt: файл

Я пытаюсь хранить двоичные данные в JCR, который создается на лету. Моя проблема в том, что единственный способ, предоставляемый JCR API, - это InputStream:

Session session = request.getResourceResolver().adaptTo(Session.class);
ValueFactory valueFactory = session.getValueFactory();
Binary bin = valueFactory.createBinary(is);

Поскольку CQ / Sling является RESTful, я могу понять, почему это так, поскольку вы обычно получаете сообщение формы или httprequest к другому источнику, где у вас всегда есть InputStream для использования. Но в моем случае я создаю двоичный файл на лету, который обычно представлен как OutputStream.

  1. Есть ли другой способ, который я упустил из виду в JCR API, где я мог бы создать OutputStream непосредственно на узле nt: file, как FileOutputStream?
  2. Если нет, есть ли простой способ преобразовать OutpuStream в InputStream?

Я знаю, что другой способ доступен в Apache Commons IOUtils.copy(). Я видел несколько примеров на SO, где они просто использовали ByteArrayOutputStream.toByteArray() для создания InputStream. Но поскольку данные могут стать довольно большими, это не лучшее решение. Кроме того, я попробовал, и почему-то поток был неполным, поэтому кажется, что есть ограничение буфера. Следующий подход был с конвейерными потоками, но у меня есть другие проблемы, для которых я открыл другой вопрос: Использование нескольких кавычек приводит к сбою PipedOutputStream / OutputStreamWriter

РЕДАКТИРОВАТЬ: удален пример кода PipedStream, поскольку я опубликовал проблему с ним в другом вопросе. Итак, я все еще ищу простой способ создать файл nt:, в котором вход не является InputStream.


person Thomas    schedule 27.11.2014    source источник


Ответы (2)


Трубы здесь - хорошее решение. Однако, чтобы реализовать их должным образом, вы должны использовать два потока: первый должен записывать данные в PipedOutputStream, а второй должен создавать Binary из PipedInputStream и сохранять его в JCR:

final PipedInputStream pis = new PipedInputStream();
final PipedOutputStream pos = new PipedOutputStream(pis);
Executors.newSingleThreadExecutor().submit(new Runnable() {         
    @Override
    public void run() {
        try {
            OutputStreamWriter writer = new OutputStreamWriter(pos);
            writer.append("append here some data");
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
});
Binary binary = session.getValueFactory().createBinary(pis);
session.getNode("/content/myNode").setProperty("xyz", binary);
session.save();

Симметричное решение, в котором вы обрабатываете JCR в новом потоке, также было бы хорошо.

person Tomek Rękawek    schedule 27.11.2014
comment
Спасибо за пример кода. Я попробовал это в модульном тесте с использованием IOUtils.toString (), и он сработал. Теперь мне нужно попробовать в CQ. - person Thomas; 27.11.2014

Вы пробовали из описанных здесь способов?

http://ostermiller.org/convert_java_outputstream_inputstream.html

Я думаю, что самые простые методы - использовать массив:

  ByteArrayOutputStream out = new ByteArrayOutputStream(); 
  //alternatively, get the outputstream of your binary file generator
  (...) //put data into out
  InputStream is = new ByteArrayInputStream(out.toByteArray())
person mish    schedule 27.11.2014
comment
Я пробовал это сначала, но результат - неполный двоичный файл в JCR - person Thomas; 27.11.2014