【问题标题】:Android NanoHTTPD Streaming content persistent connectionAndroid NanoHTTPD Streaming 内容持久连接
【发布时间】:2015-10-24 16:21:28
【问题描述】:
我一直在我们的一个应用程序中使用 NanoHTTPD 来提供内容,包括从本地 SDCard 到 Webview 的音频和视频。内容范围和内容长度标头以及 HTTP 状态已正确配置。现在,我们有一个用例,我们希望通过 NanoHTTPD 在服务器上提供内容。
NanoHTTPD 方法的问题在于它读取 Webview 请求的完整内容。如果是本地文件,它仍然可以,但你不能等待它从服务器获取这么多内容并刷新输出流。
我正在寻找一种能够打开连接并继续提供请求返回的部分数据的方法。就像在请求中获取带有范围标头的内容时一样。连接保持打开状态,只要有足够的缓冲区,视频播放器就会播放。
请帮忙。
【问题讨论】:
标签:
android
streaming
range
nanohttpd
【解决方案1】:
我通过使用 HTTP 客户端解决了这个问题。我在 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);
}