用 LFS 作極簡高效的流媒體服務

    示例可在:github git@osc 找到,包含一個詳細的圖片服務器
php

    圖片服務演示(簡單部署了 php 的服務):
java

    瀏覽圖片http://lfs2-ikcourage.myalauda.cn/testimage/image.php?type=read&id=1git

    上傳圖片:http://lfs2-ikcourage.myalauda.cn/testimage/upload.php  (圖片會自動週期性刪除)github


    先作一個音樂、視頻、圖片等媒體文件的上傳和下載示例。都只須要一行。瀏覽器

FileInputStream inputStream = new FileInputStream(file);
fileId = LFS_Stream.writeStream(FILE_NAME, fileId, inputStream, file.length());

    OK,一個媒體文件上傳成功後會返回一個文件 ID。服務器

    即便是一個比較大的視頻,好比大於 10G,也依然只有這一行代碼,並不須要作切片存儲,而且無需擔憂內存使用。(大文件的上傳也變的如此簡單)spa

    下載:.net

//讀到 readStream 中
LFS_Stream.readStream(FILE_NAME, fileId, readStream);

    沒錯,就是這一行啦,根據文件 ID 讀取文件,把數據通知給 readStream。code

    那麼,咱們來看看 readStream 作了什麼。(這就是一個完整的媒體服務的示例)視頻

IReadStream readStream = new IReadStream() {
    public boolean init(long fileId, int size, long sizeTotal, long sizeTotalRead, long offset) {
        response.setIntHeader("Content-Length", (int)sizeTotalRead);
        response.setHeader("Cache-Control", "max-age=604800");
        response.setIntHeader("Etag", 0);
        return true;
    }

    //參數好多啊,不要被嚇到了,只有前兩個是你須要用的
    //其餘的只是爲了不全局變量而已(若是須要的話,所幸,絕大多數場景都不會須要)
    public boolean parseData(byte[] b, int bytesAvalibale, int size, long sizeTotal, long sizeTotalRead, long sizeTotalReaded, long offset) {
        try {
            //這裏應實現本身的數據輸出,好比輸出到 http
            response.getOutputStream().write(b, 0, bytesAvalibale);
            return true;
        } catch (Exception e) {}
        return false;
    }
};

init 只會在 parseData 前調用一次,用來獲取文件的真實大小,好比咱們可能須要爲 http 添加 Content-Length 的頭等。

parseData 每次都會調用,把緩衝中的數據輸出到 http 的輸出流中,bytesAvalibale 是緩衝中的有效字節大小。

    到這裏你會發現,parseData 中是流式輸出數據的,因此這保證了音樂、視頻等流媒體的流暢度,而且也有效下降了服務器的內存佔用。由於緩衝的大小是很是小的,你能夠理解爲 Socket 的緩衝大小,而且可調節,默認大小 2K(注:不是帶寬的大小,這是一個遠高於帶寬的值)。

    這意味着一臺服務器,即便提供視頻服務也遊刃有餘。1W 人同時觀看視頻只須要不到 20M 的內存(資源過剩的浪費)。


    既然是流媒體服務(圖片也是,在瀏覽器中快速刷新,會看到圖片一點點的渲染),那麼斷點下載很重要,斷點上傳也很重要。

    斷點下載:

//多了兩個參數
LFS_Stream.readStream(String fileName,
    long fileId,
    IReadStream readStream,
    long offset,
    long sizeTotalRead);

    仍是那一行,只不過多了一個偏移和讀取大小而已,很簡單不是麼。

    斷點上傳:

//多了兩個參數
LFS_Stream.writeStream(String fileName,
    long fileId,
    InputStream inputStream,
    long sizeTotalWrite,
    long offset,
    long sizeTotal);

sizeTotalWrite 是要寫的大小,sizeTotal 是文件的總大小。

這句話的含義是:把文件的總大小設置爲 sizeTotal,而且在 offset 處寫入 sizeTotalWrite 大小的內容。

    上傳下載就是如此的簡單。


    LFS 的啓動

    首先從 github 獲取一個 LFS

    而後以守護模式運行 LFS --dir [存儲目錄] --daemon

    這就行了

    最後,若是須要自定義文件名的話,可使用 LFS 的索引(即:key, value)。參考上一篇內容。

相關文章
相關標籤/搜索