2008-09-25 2 views
28

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

На данный момент определения способов загрузки загрузить & выглядеть следующим образом (написано с использованием 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 ГБ), то это попытается помещать всю эту информацию в память и разбивать мою службу.

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

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

+0

Любая конкретная причина того, почему вопрос о 5 лет назад снова активен? Ответы устарели? – Loko 2013-12-20 00:06:10

ответ

6

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

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

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

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

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

+3

Концептуально вы правы, но есть определенные способы обойти это ограничение (как упоминал @spdenne). Хорошим решением будет использование MTOM. – 2009-01-30 11:46:27

+0

Это неверно. Вы можете * писать потоковое webservice. На самом деле, HttpServletResponse имеет метод getOutputStream(). – nont 2011-11-11 15:22:54

0

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

14

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

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

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

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

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

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

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

0

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

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

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

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

0

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

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

0

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

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

1

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

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

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

0

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

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

@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(); 

    } 
1

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

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

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

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

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

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

0

На самом деле не так сложно «обрабатывать 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, поэтому в браузере может возникнуть ошибка, но на самом деле это все.

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

Rodney

Смежные вопросы