Java: загрузка двоичных файлов с помощью Restlet + Apache Commons FileUpload

У меня есть REST API с Restlet 2.3, и мне нужно реализовать в нем функцию загрузки файлов. Проблема в том, что когда кто-то загружает файл с помощью POST (с типом содержимого multipart/form-data), файл достигает сервера с другой кодировкой. Чтобы проверить это, я распечатал содержимое исходного файла в терминале Unix, а затем распечатал его снова, прежде чем анализировать запрос с помощью Apache Commons FileUpload (с почти таким же кодом этого примера http://restlet.com/technical-resources/restlet-framework/guide/2.2/extensions/fileupload). Оба печатных содержимого очень похожи, но в исходном файле меньше символов, поэтому я предполагаю, что мой Java-сервер использует неправильную кодировку для интерпретации файла.

Файл, который я отправил, представляет собой изображение PNG. С текстовыми файлами сервер работает отлично, но при отправке фото или любого бинарного файла возникает проблема.


person Santiago Ignacio Poli    schedule 04.02.2015    source источник
comment
Можете ли вы использовать тип содержимого application/octet-stream?   -  person PDizzle745    schedule 04.02.2015
comment
Класс, реализующий это поведение, называется gist.github.com/santiagopoli/   -  person Santiago Ignacio Poli    schedule 04.02.2015


Ответы (3)


Я не знаю, как именно вы проверили полученный контент. Сначала вы должны проверить тип содержимого, который используется для вашей файловой части в содержимом вашего составного запроса. У вас должно получиться что-то подобное для изображения JPG:

-----------------------------75956101888331271337088331
Content-Disposition: form-data; name="fileToUpload"; filename="myimage.jpg" 
Content-Type: image/jpeg

Во-вторых, я не знаю, как вы на самом деле пишете контент, который вы получили. Apache Commons IO предоставляет служебный метод IOUtils.copy, который предоставляет простое решение для записи в OutputStream контента, полученного от InputStream. Посмотрите, как ti можно использовать в вашем контексте:

while (fileIterator.hasNext()) {
    FileItemStream fi = fileIterator.next();
    if (fi.getFieldName().equals("fileToUpload")) {
        FileOutputStream fos = new FileOutputStream(
              "output"+File.separator+fi.getFieldName());
        IOUtils.copy(fi.openStream(), fos);
        fos.close();
    }
}

ИМО, аспект кодирования применяется только к тексту, а не к двоичному содержимому.

Надеюсь, это поможет, Тьерри

person Thierry Templier    schedule 05.02.2015
comment
Спасибо за ответ, но я решил его, используя класс Google ByteStreams. - person Santiago Ignacio Poli; 05.02.2015

На самом деле я решил это, используя класс Google ByteStreams:

while (fileIterator.hasNext()) {
    FileItemStream fi = fileIterator.next();
    if (fi.getFieldName().equals(FILE_TO_UPLOAD)) {
        byte[] byteArray = ByteStreams.toByteArray(fi.openStream());
        result = new String(byteArray,Charset.forName("ISO-8859-1"));
    }
}
person Santiago Ignacio Poli    schedule 05.02.2015

У меня была аналогичная проблема при загрузке файла изображения. Вот так я исправил. Проблема заключалась в том, что в моем случае данные читались из входного потока. Поскольку он читает из сокета, нет гарантии, что у вас будет заполнен полный буфер вашего массива. Поэтому вы должны проверить размер ваших данных, прежде чем записывать их в выходной буфер/файл. Вот мой код, надеюсь, он поможет. Также доступно в репозитории https://github.com/esabilbulbul/java-servlet-fileupload/blob/master/README.md

// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload();
upload.setHeaderEncoding("UTF-8");

// Parse the request
FileItemIterator iter = upload.getItemIterator(request);
while (iter.hasNext()) 
{
    FileItemStream item = iter.next();
    String name = item.getFieldName();

    //InputStream attachmentStream = item.openStream();
    //byte[] attachmentBytes = ByteStreams.toByteArray(attachmentStream);


    //InputStream stream = item.getInputStream();
    InputStream stream = item.openStream();

    if (item.isFormField()) 
    {
        //System.out.println("Form field " + name + " with value " + Streams.asString(stream) + " detected.");
    }
    else
    {
        System.out.println("File field " + name + " with file name "+ item.getName() + " detected.");

        // Process the input stream
        FileOutputStream fout= new FileOutputStream ("c:\\" + item.getName());
        BufferedOutputStream bout= new BufferedOutputStream (fout);
        BufferedInputStream bin= new BufferedInputStream(stream);
        byte buf[] = new byte[2048];
        int len=0;
        while ((len = bin.read(buf)) > 0)//((bin.read(buf)) != -1)
        {
            bout.write(buf, 0, len);
            if (len<2048)
                len = len;
        }
        bout.close();
        bin.close();
    }        
}
person ship shuk - www.shipshuk.com    schedule 25.07.2018