Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Video download/stream using Java servlet

I am trying to download a video file in my server when the client access URL similar to this:

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.

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 tutorial but in my case i dont have file object as the inputstream just the byte array object.

help..

like image 643
harshadura Avatar asked Sep 02 '13 16:09

harshadura


1 Answers

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.

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.

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 servlet by 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.

like image 156
BalusC Avatar answered Sep 23 '22 05:09

BalusC