7

クライアントが次のような URL にアクセスするときに、サーバーにビデオ ファイルをダウンロードしようとしています。

http://localhost:8088/openmrs/moduleServlet/patientnarratives/videoDownloadServlet?videoObsId=61

このコードを試しました。しかし、うまくいきません。サーブレットにアクセスすると、空の (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();
        }
    }
}

私は BalusC の fileservletチュートリアルを使用しましたが、私の場合、バイト配列オブジェクトだけの入力ストリームとしてファイル オブジェクトを持っていません。

ヘルプ..

4

1 に答える 1

10

あなたが見つけたサーブレットは、ビデオ ファイルをストリーミングする目的にはまったく適していません。PDF、XLS などの静的ファイルの単純なファイル ダウンロード サーブレットとして意図されています。

多くのビデオ プレーヤーでは、サーバーがいわゆる HTTP レンジ リクエストをサポートしている必要があります。Rangeつまり、ヘッダー付きのリクエストによって、ビデオ ファイルの特定のバイト範囲を返すことができなければなりません。たとえば、長さが 10000 バイトのファイルのインデックス 1000 から 2000 までのバイトのみ。これは、ファイル全体をダウンロードする必要なくビデオ ストリームの特定の範囲を十分に迅速にスキップできるようにするため、および/またはビデオ ファイルの異なる部分をそれぞれ要求する複数の HTTP 接続を作成してバッファリング速度を向上させるために必須です。

ただし、これはサーブレット内の多くの追加コードであり、HTTPRange仕様を十分に理解する必要があります。すぐに使用できる例は、あなたが見つけたファイル サーブレットとまったく同じ作成者によって、この拡張ファイル サーブレットのフレーバーで提供されています。特定のケースでは、最初にファイルをローカルディスクファイルシステムベースのキャッシュに保存することをお勧めします(たとえばFile#createTempFile()、HTTPセッションのキーによって)。これにより、外部サービスから何度もファイルを取得する必要がなくなります。

于 2013-09-02T16:59:06.083 に答える