日韩一区,国产二区,欧美三区,日本大片在线看黄a∨免费,欧美人体做爰大胆视频,欧洲美女黑人粗性暴交视频,日,韩,欧美一区二区三区

首頁>文檔>技術(shù)文檔>使用http的Accept-Ranges實(shí)現(xiàn)json報(bào)文分段傳輸

此組別內(nèi)的文章

需要支持?

如果通過文檔沒辦法解決您的問題,請(qǐng)?zhí)峤还潍@取我們的支持!

使用http的Accept-Ranges實(shí)現(xiàn)json報(bào)文分段傳輸

背景

因?yàn)楣緲I(yè)務(wù)需求,對(duì)接一款終端設(shè)備,需要下載黑名單??墒窃O(shè)備的性能較差,每次下載的報(bào)文大小有限制。所以需要采用報(bào)文分段下載來實(shí)現(xiàn)。

當(dāng)然其實(shí)這種需求最好是用查詢分頁來達(dá)到分段下載是最好的,可是因?yàn)榻K端那邊實(shí)現(xiàn)問題還有以及其他各種原因,不得已采用這種分段下載方式。

找了很多帖子比較少有關(guān)于這種分段返回報(bào)文的內(nèi)容,可是有發(fā)現(xiàn)可以利用斷點(diǎn)下載的思想,去實(shí)現(xiàn)這個(gè)分段報(bào)文返回。有斷點(diǎn)下載經(jīng)驗(yàn)的同學(xué),應(yīng)該很快能理解本文介紹的內(nèi)容,其實(shí)都是很皮毛的東西。
正題

分段下載我們主要用到兩個(gè)http頭信息:

http 響應(yīng)頭 Accept-Ranges
http 請(qǐng)求頭 Range

服務(wù)器使用 HTTP 響應(yīng)頭Accept-Ranges標(biāo)識(shí)自身支持范圍請(qǐng)求(partial requests)。字段的具體值用于定義范圍請(qǐng)求的單位。當(dāng)瀏覽器/客戶端發(fā)現(xiàn) Accept-Ranges 頭時(shí),可以嘗試?yán)^續(xù)中斷了的下載,而不是重新開始。用法:Accept-Ranges: bytes

Range用來標(biāo)志本次請(qǐng)求,獲取數(shù)據(jù)的范圍。如:Range: bytes=100-200
步驟

客戶端請(qǐng)求頭都帶上Range,第一個(gè)請(qǐng)求Range:bytes=0-99,第二個(gè)Range:bytes=100-199,以此類推。
服務(wù)端除了響應(yīng)頭帶上Accept-Ranges: bytes,還需要根據(jù)請(qǐng)求中的Range來切割報(bào)文,返回Range范圍內(nèi)的數(shù)據(jù)。
http響應(yīng)碼設(shè)置為206
http響應(yīng)頭新增Content-Range,標(biāo)識(shí)本次響應(yīng)的內(nèi)容的范圍,和整個(gè)完整報(bào)文的長(zhǎng)度
需要注意一點(diǎn)的是,Range單位是byte而不是字符數(shù),所以計(jì)算長(zhǎng)度的時(shí)候要要將字符串換算成byte計(jì)算。

接下來展示controller層部分代碼:

    // 省略業(yè)務(wù)代碼
    //rsp為黑名單的響應(yīng)dto對(duì)象,全量的黑名單
    String returnJson = JsonUtil.Object2Json(rsp);
    httpResp.setContentType("application/json");
    //無緩存
    httpResp.setHeader("Cache-Control", "no-cache");
    //設(shè)置UTF-8編碼
    httpResp.setCharacterEncoding(Constant.CHARACTER_ENCODING);
    //可以斷點(diǎn)下載
    httpResp.setHeader("Accept-Ranges", "bytes");
    //設(shè)置http響應(yīng)碼為206
    httpResp.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);

    //獲取頭信息Range,并且去掉bytes=
    String range = httpReq.getHeader("Range").replaceAll("bytes=", "");
    String[] rangeSplit = range.split("-");

    //整段報(bào)文的總長(zhǎng)度,要用utf-8的編碼字節(jié)長(zhǎng)度計(jì)算
    int returnJsonLength = returnJson.getBytes("UTF-8").length;
    //offset 第一次請(qǐng)求默認(rèn)從0開始
    int offset = Integer.parseInt(rangeSplit[0]);
    // 初始化 length 和 endIndex
    // length:本次報(bào)文返回的長(zhǎng)度;endIndex:本次報(bào)文結(jié)束的下標(biāo)位置,默認(rèn)是報(bào)文的總長(zhǎng)度所以是returnJsonLength - 1
    int length = returnJsonLength - offset;
    int endIndex = returnJsonLength - 1;
    //設(shè)置 length 和 endIndex 值
    if (rangeSplit.length > 1) {
        //strSplit數(shù)組長(zhǎng)度大于1,說明Range是一個(gè)范圍,而不是一個(gè)固定值
        endIndex = Integer.parseInt(rangeSplit[1]);
        //endIndex不允許大于等于報(bào)文長(zhǎng)度
        if (endIndex >= returnJsonLength) {
            endIndex = returnJsonLength - 1;
        }
        //因?yàn)閑ndIndex最大值比報(bào)文長(zhǎng)度小于1的,而length是報(bào)文返回長(zhǎng)度,所以要+1
        length = endIndex - offset + 1;
    }

    httpResp.setHeader("Content-Length", Long.toString(returnJsonLength));
    //Content-Range:bytes[json的開始字節(jié)]-[json的結(jié)束字節(jié)]/[報(bào)文的總大小]
    httpResp.setHeader("Content-Range", "bytes " + offset + "-" + endIndex + "/" + returnJsonLength);

    // 獲得寫出流
    try {
        OutputStream outputStream = httpResp.getOutputStream();
        //重點(diǎn)來了,輸出報(bào)文,只返回原完整報(bào)文的offset至offset + length的字節(jié)內(nèi)容
        outputStream.write(returnJson.getBytes("utf-8"), offset, length);
        outputStream.flush();
        outputStream.close();
    } catch (Exception e) {
        LogUtil.addProclog(procid, "返回報(bào)文錯(cuò)誤:" + CommonUtil.getTrace(e));
    }

缺點(diǎn):

每次請(qǐng)求只返回部分的報(bào)文,可是每次都是獲取全量的黑名單,數(shù)據(jù)庫查詢多次??梢杂胷edis緩存黑名單,減少數(shù)據(jù)庫查詢。僅以記錄本次的解決方案,如果有更好的思路不妨一起交流一下,不才獻(xiàn)丑了。

0 條回復(fù) A文章作者 M管理員
    暫無討論,說說你的看法吧
QQ客服
  • QQ176363189 點(diǎn)擊這里給我發(fā)消息
旺旺客服
  • 速度網(wǎng)絡(luò)服務(wù)商 點(diǎn)這里給我發(fā)消息
電子郵箱
  • sudu@yunjiasu.cc
微信客服
  • suduwangluo