Android端大文件上傳:分片上傳,斷點(diǎn)續(xù)傳(含demo)

前言
Android端在遇到一些需要上傳文件或者視頻的項(xiàng)目時嘲碧,后端一般都會要求我們進(jìn)行分片上傳和秒傳校驗(yàn)。因?yàn)檫@樣就不會上傳重復(fù)的文件,也不會占用網(wǎng)絡(luò)帶寬朱巨。當(dāng)然,對于我們app端來說枉长,畢竟很少有人會忍受冀续,當(dāng)文件上傳到一半中斷后,繼續(xù)上傳卻只能重頭開始上傳必峰,這種讓人不爽的體驗(yàn)洪唐。

詳細(xì)教程
1、什么是秒傳
通俗的說吼蚁,你把要上傳的東西的唯一標(biāo)識(md5標(biāo)識)傳遞給服務(wù)器凭需,服務(wù)器識別是否存在該文件,如果存在就不需要上傳肝匆,直接可獲取文件信息粒蜈。

2、什么是分片上傳
分片上傳旗国,就是把要上傳的文件切割成多個小的數(shù)據(jù)類型進(jìn)行分別上傳枯怖,服務(wù)器那邊獲取這些多個數(shù)據(jù),再度整個成一個完整的文件能曾。

3度硝、什么是斷點(diǎn)續(xù)傳
一般是指肿轨,在上一次分片上傳中,由于網(wǎng)絡(luò)或者其他原因蕊程,后面幾片的子數(shù)據(jù)未上傳成功椒袍。在第二次上傳時,可調(diào)用秒傳接口藻茂,返回已上傳成功的分片序號驹暑,可跳過前幾片已上傳的分片,直接進(jìn)行未上傳的分片開始上傳辨赐。

封裝工具類使用方式

  UploadFileUtils.with(this)
                .loadFile(videopath,videoname)
                .setBustype("mbustype")
                .setUpLoadListener(new UploadFileUtils.OnUpLoadListener() {
                    @Override
                    public void start() {
                        showTip("上傳中");
                    }
                    @Override
                    public void onUpload(int currentnum, int allnum) {
                        showTip(String.format("%s%d%s", "上傳",currentnum * 100 / allnum, "%"));
                    }
                    @Override
                    public void onComplete(int filesourceId) {
                        showTip("上傳100%");
                        //獲取id优俘,然后自己可以做處理
                    }
                    @Override
                    public void onUploadFailed(String errormessage) {
                        dismissTip();
                    }
                }).launch();

流程邏輯
①、獲取文件的md5值(注:md5的獲取是延時性操作肖油,不能在主線程操作兼吓,需單開線程獲取)森枪。
②视搏、調(diào)用秒傳接口獲取服務(wù)器是否存在該文件,如果不存在县袱,獲取是否存在其分片浑娜。
③、開始對文件進(jìn)行切片和上傳式散,如果是已上傳過的分片序號筋遭,則跳過進(jìn)行下一個分片上傳。

核心代碼

 private void start(){
        if (null != onUpLoadListener) {
            onUpLoadListener.start();
        }
        new Thread() {
            @Override
            public void run() {
                filemd5 = MD5Util.getFileMD5(getfilepath);   //文件轉(zhuǎn)md5耗時操作暴拄,需要在子線程執(zhí)行
                mHandler.sendEmptyMessage(0x123);
            }
        }.start();
    }

    private Handler mHandler = new Handler(Looper.getMainLooper()){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == 0x123){
                checkvideofile(getfilepath,getfilename,getbustype);
            }
        }
    };

    //秒傳接口 校驗(yàn)文件
    private void checkvideofile(String mfilepath, String mfilename,String mbustype){
        EasyHttp.get("秒傳接口")
                .params("busType", mbustype)   //文件類型 固定為doc
                .params("checksum", filemd5)   //文件 md5加密
                .params("fileName", mfilename)   //文件名
                .params("size", ((int) FileSizeUtil.getFileOrFilesSize(mfilepath, FileSizeUtil.SIZETYPE_B)) + "")
                .execute(new SimpleCallBack<CheckFileEntity>() {
                    @Override
                    public void onError(ApiException e) {
                        Toast.makeText(mcontext, e.getMessage(), Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onSuccess(CheckFileEntity response) {
                        if (response.getData().isFileExists()){
                            if (null != onUpLoadListener) {
                                onUpLoadListener.onComplete(response.getData().getSourceId());
                            }
                        }else {
                            haveuploadfilenum = new ArrayList<>();
                            if (null!=response.getData().getChunkList()&&response.getData().getChunkList().size()>0){
                                haveuploadfilenum = response.getData().getChunkList();
                            }
                            cutfile(mfilepath);
                        }

                    }
                });
    }

    private void cutfile(String filePath){
        try {
            long mBufferSize = 1024 * 1024 * 2; //分片的大小漓滔,可自定義
            fileCutUtils = new FileCutUtils();
            littlefilecount = fileCutUtils.getSplitFile(new File(filePath), mBufferSize);
            littlefilelist = fileCutUtils.getLittlefilelist();

            uploadFile(0);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void uploadFile(int filenum) {
        boolean isRepeat = false;
        if (null!=haveuploadfilenum&&haveuploadfilenum.size()>0){   //之前傳過的num就不用傳
            for (int uploadfilenum:haveuploadfilenum){
                if (filenum == uploadfilenum){
                    isRepeat = true;
                }
            }
        }

        if (isRepeat&&null!=haveuploadfilenum&&haveuploadfilenum.size()>0){
            uploadFile(filenum+1);
        }else {
            EasyHttp.post("上傳接口")
                    .params("busType", getbustype)   //上傳類型
                    .params("checksum", filemd5)   //文件路徑 md5加密
                    .params("chunk", String.valueOf(filenum))   //切片編號
                    .params("chunks", String.valueOf(littlefilecount))   //切片總數(shù)
                    .params("chunkSize", "分片的大小")   //分片大小
                    .params("file", littlefilelist.get(filenum), getfilename, null)
                    .execute(new SimpleCallBack<UploadEntity>() {
                        @Override
                        public void onError(ApiException e) {
                            if (null != onUpLoadListener) {
                                onUpLoadListener.onUploadFailed(e.getMessage());
                            }
                            getfilepath = "";
                            getfilename = "";
                            getbustype = "";
                            filemd5 = "";

                            littlefilecount = 0;
                            if (null!=haveuploadfilenum){
                                haveuploadfilenum.clear();
                            }
                            if (null!=littlefilelist){
                                littlefilelist.clear();
                            }

                            fileCutUtils.deleteLittlelist();
                        }

                        @Override
                        public void onSuccess(UploadEntity response) {
                            if (filenum<(littlefilecount-1)){
                                if (null != onUpLoadListener) {
                                    onUpLoadListener.onUpload(filenum+1,littlefilecount);
                                    uploadFile(filenum+1);
                                }
                            }else {   //上傳完成
                                if (null != onUpLoadListener) {
                                    onUpLoadListener.onComplete(response.getData().getCommonSourceId());
                                }

                                getfilepath = "";
                                getfilename = "";
                                getbustype = "";
                                filemd5 = "";

                                littlefilecount = 0;
                                if (null!=haveuploadfilenum){
                                    haveuploadfilenum.clear();
                                }
                                if (null!=littlefilelist){
                                    littlefilelist.clear();
                                }

                                fileCutUtils.deleteLittlelist();
                            }
                        }
                    });
        }
    }

點(diǎn)擊此處獲取分片上傳demo

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市乖篷,隨后出現(xiàn)的幾起案子响驴,更是在濱河造成了極大的恐慌,老刑警劉巖撕蔼,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件豁鲤,死亡現(xiàn)場離奇詭異,居然都是意外死亡鲸沮,警方通過查閱死者的電腦和手機(jī)琳骡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來讼溺,“玉大人楣号,你說我怎么就攤上這事。” “怎么了竖席?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵耘纱,是天一觀的道長敬肚。 經(jīng)常有香客問我毕荐,道長,這世上最難降的妖魔是什么艳馒? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任憎亚,我火速辦了婚禮,結(jié)果婚禮上弄慰,老公的妹妹穿的比我還像新娘第美。我一直安慰自己,他們只是感情好陆爽,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布什往。 她就那樣靜靜地躺著,像睡著了一般慌闭。 火紅的嫁衣襯著肌膚如雪别威。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天驴剔,我揣著相機(jī)與錄音省古,去河邊找鬼。 笑死丧失,一個胖子當(dāng)著我的面吹牛豺妓,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播布讹,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼琳拭,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了描验?” 一聲冷哼從身側(cè)響起白嘁,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤挠乳,失蹤者是張志新(化名)和其女友劉穎权薯,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體睡扬,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡盟蚣,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了卖怜。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片屎开。...
    茶點(diǎn)故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖马靠,靈堂內(nèi)的尸體忽然破棺而出奄抽,到底是詐尸還是另有隱情蔼两,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布逞度,位于F島的核電站额划,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏档泽。R本人自食惡果不足惜俊戳,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望馆匿。 院中可真熱鬧抑胎,春花似錦、人聲如沸渐北。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽赃蛛。三九已至恃锉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間焊虏,已是汗流浹背淡喜。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留诵闭,地道東北人炼团。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像疏尿,于是被迫代替她去往敵國和親瘟芝。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 前言 文件上傳是一個老生常談的話題了贸宏,在文件相對比較小的情況下,可以直接把文件轉(zhuǎn)化為字節(jié)流上傳到服務(wù)器磕洪,但在文件比...
    碼農(nóng)突圍閱讀 748評論 0 2
  • 16宿命:用概率思維提高你的勝算 以前的我是風(fēng)險厭惡者吭练,不喜歡去冒險,但是人生放棄了冒險析显,也就放棄了無數(shù)的可能鲫咽。 ...
    yichen大刀閱讀 6,038評論 0 4
  • 公元:2019年11月28日19時42分農(nóng)歷:二零一九年 十一月 初三日 戌時干支:己亥乙亥己巳甲戌當(dāng)月節(jié)氣:立冬...
    石放閱讀 6,875評論 0 2