Android实现大文件的分片上传与断点续传


前言

最近在公司的开发任务中,有一个大文件需要分片上传的功能要求,由于之前没有做过这个功能,看了一下网上的博客,有看到生成一些小文件再上传的,感觉不是很好,所以在这记录一下最后的代码,希望能跟大家交流一下


代码

1.将需要上传的文件分片处理

分块方法

	/**
     * @param offset 偏移量
     * @param file  分块文件
     * @param blockSize 每块的大小
     * @return  这一片的数据
     */
    private byte[] getBlock(long offset, File file, int blockSize) {
        byte[] result = new byte[blockSize];
        try (RandomAccessFile accessFile = new RandomAccessFile(file, "r")) {
            accessFile.seek(offset);
            int readSize = accessFile.read(result);
            if (readSize == -1) {
                return null;
            } else if (readSize == blockSize) {
                return result;
            } else {
                byte[] byteArray = new byte[readSize];
                System.arraycopy(result, 0, byteArray, 0, readSize);
                return byteArray;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

2.将分片数据上传

private void uploadFile(String filePath){
        File file = new File(filePath);
        if (file .exists()){
        	//md5值是后台接口需要
            String md5 = getFileMD5(file );
            //计算文件分片的总块数
            long totalBlock = sourceFile.length() / PART_SIZE + (sourceFile.length() % PART_SIZE > 0 ? 1 : 0);
          	//不要怀疑Math.max(totalBlock,1)的用法,因为我要上传0长度但有内容的文件(真的有!)
          	uploadFile(filePath,file.getName(),file.length(),Math.max(totalBlock,1),1,md5);
        } else {
        	//不存在则回调错误方法
            msg.append("file not exists");
            onError();
        }
    }
    
private void uploadFile(String filePath, String fileName, long totalSize, long totalBlock, int currentBlock, String md5){
        File file = new File(filePath);
        byte[] fileStream = getBlock((currentBlock-1)*PART_SIZE,file,PART_SIZE);
        if (fileStream == null) {
            msg.append("getBlock error");
            onError();
            return;
        }
        MultipartBody.Builder builder = new MultipartBody.Builder();
        builder.setType(MultipartBody.FORM);
        builder.addFormDataPart("totalSize", String.valueOf(totalSize))
            .addFormDataPart("totalBlock", String.valueOf(totalBlock))
            .addFormDataPart("currentBlock", String.valueOf(currentBlock))
            .addFormDataPart("md5",md5)
            .addFormDataPart("type","file");
        RequestBody body = RequestBody.create(MultipartBody.FORM, fileStream);
        builder.addFormDataPart("file", fileName, body);
        RetrofitUtil.upload(token,builder.build()).enqueue(new Callback<UploadSuccess>() {
            @Override
            public void onResponse(Call<UploadSuccess> call, Response<UploadSuccess> response) {
                UploadSuccess success = response.body();
                if (success != null) {
                    if (success.isStatus()) {
                        if (currentBlock == totalBlock) {
                            onSuccess();
                        } else {
                            // 在回调里面上传下一分片,比直接循环更加友好
                            uploadFile(filePath,fileName,totalSize,totalBlock,currentBlock+1,md5,callBack);
                        }
                    } else {
                        msg.append(success.getMsg());
                        onError();
                    }
                }
            }

            @Override
            public void onFailure(Call<UploadSuccess> call, Throwable t) {
                msg.append(t.getMessage());
                t.printStackTrace();
                onError();
            }
        });
    }

3.Retrofit上传接口

    @POST("api/upload")
    Call<UploadSuccess> upload(@Header("Authorization")String token, @Body RequestBody requestBody);

总结

我不知道这些代码有没有更好的写法,有的话在评论下面告诉我吧,也希望能给没做过分片上传文件的伙伴一个思路,如果需要实现断点续传的话,只需要记录哪些分片已经上传成功,在恢复上传的时候上传之后的分片,最终后台就可以合并成完整的文件了,加油工程师们!觉得不错的话就点个赞吧

本文链接https://blog.csdn.net/weixin_44337681/article/details/112900048
未经允许,请勿转载!

  • 9
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白白猪

感谢兄弟的支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值