Подтвердить что ты не робот

Может ли веб-служба вернуть поток?

Я пишу небольшое приложение, которое позволит людям загружать и загружать файлы мне. Я добавил веб-сервис для этого приложения, чтобы предоставить возможность загрузки/загрузки таким образом, но я не слишком уверен в том, насколько хорошо моя реализация будет справляться с большими файлами.

В настоящее время определения методов загрузки и загрузки выглядят так (написано с использованием Apache CXF):

boolean uploadFile(@WebParam(name = "username") String username,
    @WebParam(name = "password") String password,
    @WebParam(name = "filename") String filename,
    @WebParam(name = "fileContents") byte[] fileContents)
    throws UploadException, LoginException;

byte[] downloadFile(@WebParam(name = "username") String username,
    @WebParam(name = "password") String password,
    @WebParam(name = "filename") String filename) throws DownloadException,
    LoginException;

Таким образом, файл загружается и загружается в виде байтового массива. Но если у меня есть файл с каким-то глупым размером (например, 1 ГБ), то он попытается помещать всю эту информацию в память и разбивать мои сервисы.

Итак, мой вопрос: вместо этого можно вернуть какой-то поток? Я бы предположил, что это не будет ужасно независимым от ОС. Хотя я знаю теорию, лежащую в основе веб-сервисов, практическая сторона - это то, что мне все еще нужно получить немного информации.

Приветствия для любого ввода, Ли

4b9b3361

Ответ 1

Stephen Denne имеет реализацию Metro, которая удовлетворяет вашим требованиям. Мой ответ приведен ниже, после краткого объяснения, почему это так.

Большинство реализаций веб-сервисов, которые построены с использованием HTTP в качестве протокола сообщений, соответствуют требованиям REST, поскольку они допускают только простые шаблоны send-receive и не более того. Это значительно улучшает взаимодействие, так как все различные платформы могут понять эту простую архитектуру (например, веб-сервис Java, говорящий с веб-службой .NET).

Если вы хотите сохранить это, вы можете предоставить chunking.

boolean uploadFile(String username, String password, String fileName, int currentChunk, int totalChunks, byte[] chunk);

Это потребует некоторой работы в тех случаях, когда вы не получите куски в правильном порядке (или вы можете просто потребовать, чтобы куски пришли в правильном порядке), но, вероятно, это будет довольно легко реализовать.

Ответ 2

Да, это возможно с Metro. См. Пример Large Attachments, который выглядит так, как будто он делает то, что вы хотите.

JAX-WS RI обеспечивает поддержку отправки и приема больших вложений потоковым способом.

  • Используйте MTOM и DataHandler в модели программирования.
  • Передача DataHandler в StreamingDataHandler и использование его методов.
  • Убедитесь, что вы вызываете StreamingDataHandler.close(), а также закрываете поток StreamingDataHandler.readOnce().
  • Включить HTTP-chunking на стороне клиента.

Ответ 3

Когда вы используете стандартизованный веб-сервис, отправитель и получатель полагаются на целостность отправки данных XML от одного к другому. Это означает, что запрос веб-службы и ответ только завершены при отправке последнего тега. Имея это в виду, веб-сервис нельзя рассматривать как поток.

Это логично, потому что стандартизированные веб-службы полагаются на http-протокол. Этот "без гражданства", скажет, что он работает как "открытое соединение... отправить запрос... получить данные... закрыть запрос". Во всяком случае, соединение будет закрыто. Так что что-то вроде потоковой передачи не предназначено для использования здесь. Или он слоями выше http (например, веб-сервисы).

Так жаль, но насколько я вижу, нет возможности для потоковой передачи в веб-сервисах. Еще хуже: в зависимости от реализации/конфигурации веб-службы байт [] - данные могут быть переведены на Base64, а не на CDATA-тег, и запрос может стать еще более раздутым.

P.S.: Да, как писали другие, возможно "чутье". Но это не поток, как таковой;-) - во всяком случае, это может вам помочь.

Ответ 4

Для WCF я думаю, что его можно определить члена в сообщении как поток и установить привязку соответствующим образом - я видел эту работу с wcf, говорящим с веб-службой Java.

Вам нужно установить transferMode = "StreamedResponse" в конфигурации httpTransport и использовать mtomMessageEncoding (необходимо использовать раздел настраиваемого связывания в конфиге).

Я думаю, что одно ограничение состоит в том, что вы можете иметь только один элемент тела сообщения, если хотите потокочет (какой смысл имеет смысл).

Ответ 5

Apache CXF поддерживает потоки отправки и получения.

Ответ 6

Мне не нравится разбивать его тем, кто думает, что потоковая веб-служба невозможна, но на самом деле все HTTP-запросы основаны на потоках. Каждый браузер, выполняющий GET на веб-сайт, основан на потоке. Каждый вызов веб-службы основан на потоке. Да все. Мы не замечаем этого на том уровне, где мы реализуем сервисы или страницы, потому что более низкие уровни архитектуры имеют дело с этим для вас - но это делается.

Вы когда-нибудь замечали в браузере, что иногда может потребоваться некоторое время, чтобы получить страницу - браузер просто держится, показывая песочные часы? Это связано с тем, что браузер ожидает поток.

Потоки - это причина, по которой mime/types должны быть отправлены до фактических данных - это всего лишь поток байтов в браузере, он не сможет идентифицировать фотографию, если вы не сказали ей, что это было первым, Кроме того, почему вы должны передать размер двоичного файла перед отправкой - браузер не сможет определить, где изображение остановится, и страница снова забирается.

Это всего лишь поток байтов для клиента. Если вы хотите доказать это для себя, просто удержите выходной поток в любой момент обработки запроса и закройте его(). Вы взорвете все. Браузер немедленно прекратит показ песочных часов и отобразит "не может найти" или "соединение reset на сервере" или какое-то другое такое сообщение.

То, что многие люди не знают, что весь этот материал основан на потоках, показывает, насколько много материала было наложено поверх него. Некоторые скажут слишком много вещей - я один из них.

Удачи и счастливого развития - расслабьте плечи!

Ответ 7

Один из способов сделать это - добавить метод uploadFileChunk (byte [] chunkData, int size, int offset, int totalSize) (или что-то в этом роде), который загружает части файла и серверы записывают его на диск.

Ответ 8

Имейте в виду, что запрос веб-службы в основном сводится к одному HTTP POST.

Если вы посмотрите на вывод файла .ASMX в .NET, он точно покажет вам, как будет выглядеть запрос и ответ POST.

Chunking, как упоминается @Guvante, будет самым близким к тому, что вы хотите.

Я предполагаю, что вы могли бы реализовать свой собственный код веб-клиента для обработки TCP/IP и потокового вещания в ваше приложение, но это было бы сложно сказать.

Ответ 9

Я думаю, что использование простого сервлета для этой задачи было бы намного проще, или есть какая-то причина, по которой вы не можете использовать сервлет?

Например, вы можете использовать Commons библиотеку с открытым исходным кодом.

Ответ 10

Библиотека RMIIO для Java обеспечивает передачу RemoteInputStream через RMI - нам нужен только RMI, хотя вы должны быть в состоянии адаптировать код для работы над другими типами RMI. Это может помочь вам, особенно если вы можете иметь небольшое приложение на стороне пользователя. Библиотека была разработана с целью ограничить размер данных, перемещаемых на сервер, чтобы избежать точно такого типа ситуации, который вы описываете, - эффективно атака DOS, заполняя RAM или диск.

В библиотеке RMIIO сторона сервера принимает решение о том, сколько данных он хочет вытащить, где с помощью HTTP PUT и POST клиент получает это решение, включая скорость, с которой он нажимает.

Ответ 11

Да, веб-сервис может выполнять потоковое вещание. Я создал веб-сервис с использованием Apache Axis2 и MTOM для поддержки рендеринга PDF-документов из XML. Поскольку результирующие файлы могут быть довольно большими, потоковая передача важна, потому что мы не хотим хранить все это в памяти. Взгляните на документацию Oracle на потоковое вложение SOAP.

В качестве альтернативы вы можете сделать это самостоятельно, а tomcat создаст заголовки Chunked. Это пример функции контроллера spring, которая передает потоки.

 @RequestMapping(value = "/stream")
        public void hellostreamer(HttpServletRequest request, HttpServletResponse response) throws CopyStreamException, IOException  
{

            response.setContentType("text/xml");
            OutputStreamWriter writer = new OutputStreamWriter (response.getOutputStream());
            writer.write("this is streaming");
            writer.close();

    }

Ответ 12

На самом деле не так сложно "обрабатывать TCP/IP и передавать информацию в ваше приложение". Попробуйте это...

class MyServlet extends HttpServlet
{
    public void doGet(HttpServletRequest request, HttpServletResponse response)
    {
        response.getOutputStream().println("Hello World!");
    }
}

И это все, что есть. В приведенном выше коде вы ответили на HTTP-запрос GET, отправленный из браузера, и вернули в этот браузер текст "Hello World!".

Имейте в виду, что "Hello World!" недействителен HTML, поэтому в браузере может возникнуть ошибка, но на самом деле это все, что нужно.

Удача в вашем развитии!

Родни