使用 Java servlet 的视频下载/流
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18577307/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Video download/stream using Java servlet
提问by harshadura
I am trying to download a video file in my server when the client access URL similar to this:
当客户端访问 URL 类似于以下内容时,我试图在我的服务器中下载视频文件:
http://localhost:8088/openmrs/moduleServlet/patientnarratives/videoDownloadServlet?videoObsId=61
I have tried this code. But its not working. When i visit the servlet it only download a Blank (0 size) file.
我试过这个代码。但它不起作用。当我访问 servlet 时,它只下载一个空白(0 大小)文件。
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
try {
Integer videoObsId = Integer.parseInt(request.getParameter("videoObsId"));
Obs complexObs = Context.getObsService().getComplexObs(videoObsId, OpenmrsConstants.RAW_VIEW);
ComplexData complexData = complexObs.getComplexData();
Object object2 = complexData.getData(); // <-- an API used in my service. this simply returns an object.
byte[] videoObjectData = SerializationUtils.serialize(object2);
// Get content type by filename.
String contentType = null;
if (contentType == null) {
contentType = "application/octet-stream";
}
// Init servlet response.
response.reset();
response.setBufferSize(DEFAULT_BUFFER_SIZE);
response.setContentType(contentType);
response.setHeader("Content-Length", String.valueOf(videoObjectData.length));
response.setHeader("Content-Disposition", "attachment; filename=\"" + "test.flv" + "\"");
// Prepare streams.
BufferedInputStream input = null;
BufferedOutputStream output = null;
try {
// Open streams.
input = new BufferedInputStream(new ByteArrayInputStream(videoObjectData), DEFAULT_BUFFER_SIZE);
output = new BufferedOutputStream(response.getOutputStream(), DEFAULT_BUFFER_SIZE);
// Write file contents to response.
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
int length;
while ((length = input.read(buffer)) > 0) {
output.write(buffer, 0, length);
}
} finally {
// Gently close streams.
close(output);
close(input);
}
}
// Add error handling above and remove this try/catch
catch (Exception e) {
log.error("unable to get file", e);
}
}
private static void close(Closeable resource) {
if (resource != null) {
try {
resource.close();
} catch (IOException e) {
// Do your thing with the exception. Print it, log it or mail it.
e.printStackTrace();
}
}
}
I have used BalusC's fileservlet tutorialbut in my case i dont have file object as the inputstream just the byte array object.
我使用过 BalusC 的fileservlet 教程,但在我的情况下,我没有文件对象作为输入流,只是字节数组对象。
help..
帮助..
采纳答案by BalusC
The servlet which you found is indeed insuitable for the purpose of streaming a video file. It's more intented as a simple file download servlet for static files like PDF, XLS, etc.
您发现的 servlet 确实不适合用于流式传输视频文件。它更像是一个简单的文件下载 servlet,用于静态文件,如 PDF、XLS 等。
A lot of video players require that the server supports so-called HTTP range requests. I.e. it must be able to return a specific byte range of the video file by a request with a Range
header. For example, only the bytes from index 1000 until 2000 on a file of 10000 bytes long. This is mandatory in order to be able to skip a certain range of the video stream quickly enough without the need to download the whole file and/or to improve buffering speed by creating multiple HTTP connections which each requests a different part of the video file.
许多视频播放器要求服务器支持所谓的 HTTP 范围请求。即它必须能够通过带有Range
标头的请求返回视频文件的特定字节范围。例如,在 10000 字节长的文件中,只有从索引 1000 到 2000 的字节。这是强制性的,以便能够在不需要下载整个文件的情况下足够快地跳过特定范围的视频流和/或通过创建多个 HTTP 连接来提高缓冲速度,每个连接请求视频文件的不同部分。
This is however a lot of additional code in the servlet which requires a well understanding of the HTTP Range
specification. A ready to use example is provided in flavor of this extended file servletby the very same author of the file servlet which you found. In your specific case it's perhaps recommendable to save the file to local disk file system based cache first (e.g. by File#createTempFile()
and some key in HTTP session), so that you don't need to obtain it from the external service again and again.
然而,这是 servlet 中的许多附加代码,需要对 HTTPRange
规范有很好的理解。您找到的文件 servlet 的作者是这个扩展文件 servlet的风格,提供了一个随时可用的示例。在您的特定情况下,可能建议首先将文件保存到基于缓存的本地磁盘文件系统(例如,通过File#createTempFile()
HTTP 会话中的某些密钥),这样您就不需要一次又一次地从外部服务获取它。