2015-10-24 5 views
0

Я использую NanoHTTPD в одном из наших приложений для обслуживания контента, включая аудио и видео с локальной SDCard, на веб-просмотр. Правильно настроены заголовки содержимого и заголовки длины контента вместе с HTTP-статусом. Теперь у нас есть прецедент, где мы хотим обслуживать контент на сервере через NanoHTTPD.Android NanoHTTPD Постоянное соединение потокового контента

Проблема с подходом NanoHTTPD заключается в том, что он считывает полный контент, на который запрашивает веб-просмотр. В случае локального файла все равно Ok, но вы не можете дождаться, когда он выберет столько контента с сервера и очистит выходной поток.

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

Пожалуйста, помогите.

ответ

0

Я решил это с помощью HTTP Client. Я зарегистрировал шаблон на localhost с уникальным портом и обработал ответ для больших носителей, добавив соответствующие заголовки, статус и длину содержимого. Три вещи здесь:

1) Копировать заголовки из ответа HTTP на локальный ответ
2) Установить код ответа. Полное содержание (200) или частичное содержание (206)
3) Создать новую InputStreamEntity и добавить его в ответ

@Override 
    public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException { 
     String range = null; 
     //Check if there's range in request header 
     Header rangeHeader = request.getFirstHeader("range"); 

     if (rangeHeader != null) { 
      range = rangeHeader.getValue(); 
     } 

     URL url = new URL(mediaURL); 
     URLConnection urlConn = url.openConnection(); 

     if (!(urlConn instanceof HttpURLConnection)) { 
      throw new IOException("URL is not an Http URL"); 
     } 
     HttpURLConnection httpConn = (HttpURLConnection) urlConn; 
     httpConn.setRequestMethod("GET"); 

     //If range is present, direct HTTPConnection to fetch data for that range only  
     if(range!=null){ 
      httpConn.setRequestProperty("Range",range); 
     } 
     //Add any custom header to request that you want and then connect. 
     httpConn.connect(); 

     int statusCode = httpConn.getResponseCode(); 

     //Copy all headers with valid key to response. Exclude content-length as that's something response gets from the entity. 
     Map<String, List<String>> headersMap = httpConn.getHeaderFields(); 
     for (Map.Entry<String, List<String>> entry : headersMap.entrySet()) 
     { 
      if(entry.getKey() != null && !entry.getKey().equalsIgnoreCase("content-length")) { 
       for (int i = 0; i < entry.getValue().size(); i++) { 
        response.setHeader(entry.getKey(), entry.getValue().get(i)); 
       } 
      } 
     } 

     //Important to set correct status code 
     response.setStatusCode(statusCode); 

     //Pass the InputStream to response and that's it. 
     InputStreamEntity entity = new InputStreamEntity(httpConn.getInputStream(), httpConn.getContentLength()); 
     entity.setContentType(httpConn.getContentType()); 
     response.setEntity(entity); 

    }