当前位置: 代码网 > it编程>App开发>Android > Android 文件分段上传和下载实现方案

Android 文件分段上传和下载实现方案

2024年11月25日 Android 我要评论
一、背景android 中的大文件下载需要使用分段下载,下载通常是在线程中进行的,假如有5段,那同时5个线程去执行下载,请求http返回文件流后,需要将多个文件流同时写进同一个文件,这里用到rando

一、背景

android 中的大文件下载需要使用分段下载,下载通常是在线程中进行的,假如有5段,那同时5个线程去执行下载,请求http返回文件流后,需要将多个文件流同时写进同一个文件,这里用到

randomaccessfile

分段上传的话,只需要根据每段文件阀值,例如,50m为一段,将文件按照设置的阀值,分段上传即可

二、相关代码

2.1 分段上传关键代码

忽略网络请求和状态码,每个人接口定义的的请求参数和返回code不一样

       private val default_block_size: long = 50 * 1024 * 1024 //50mb
        val blocksize=default_block_size
        val randomaccessfile = randomaccessfile(filepath, "r")
        val filelen = randomaccessfile.length()
        //超过设定的单个文件大小,需要分块上传
            val blockfilenum = math.ceil((filelen / blocksize.todouble())).toint()
            xlogutil.d("${tag}blockfilenum:$blockfilenum,,,,filelen:$filelen,,,blocksize:$blocksize,,,requestid:$requestid")
            var offset = 0l
            var successnum = 0
            var issendresult = true
            for (i in 0 until blockfilenum) {
                val startoffset = i * blocksize
                val blockfilelen = math.min(blocksize, filelen - startoffset)
                val filedata = getfiledata(filepath, offset, blockfilelen.toint())
                // 创建文件名请求体
                val requestbody = requestbody.create(null, filedata)
                val call = retrofitclient.getuploadfileservice(
                    token,
                    requestid,
                    offset.tostring(),
                    uploadtype
                ).uploadfile(file.name, requestbody)
                xlogutil.d("${tag}upload 第${i + 1}块 block file,offset:$offset,,,blockfilelen:$blockfilelen,,,blockfilenum:$blockfilenum,,,filelen:$filelen,,,filepath:$filepath,,,filedata size:${filedata?.size},,,requestid:$requestid")
                offset += blockfilelen
                call.enqueue(object : callback<responsebody?> {
                    override fun onresponse(
                        call: call<responsebody?>,
                        response: response<responsebody?>
                    ) {
                        val code = response.code()
                        xlogutil.d("${tag}upload 第${i + 1}块 block file result code:$code,,,requestid:$requestid")
                        if (code == 201) {
                            //处理成功响应
                            successnum++
                            if (successnum == blockfilenum) {
                                xlogutil.d("${tag}upload all block file success,blockfilenum:$blockfilenum,,,requestid:$requestid")
                                listener?.apply {
                                    onsuccess(constant.success, requestid)
                                }
                                //上传完
                            }
                        } else {
                            //处理失败响应
                        }
                    }
                    override fun onfailure(call: call<responsebody?>, t: throwable) {
                        // 处理请求失败
                        xlogutil.d("${tag}upload 第${i + 1}块 block file onfailure message:${t.printstacktrace()}")
                    }
                })
            }
    /**
     * 根据偏移量获取分块文件数据
     */
    fun getfiledata(filepath: string, offset: long, length: int): bytearray? {
        // 使用randomaccessfile随机访问文件
        var randomaccessfile: randomaccessfile? = null
        try {
            randomaccessfile = randomaccessfile(filepath, "r")
            val filechannel = randomaccessfile.channel
            // 将文件的部分区域映射为内存区域
            val mappedbytebuffer =
                filechannel.map(filechannel.mapmode.read_only, offset, length.tolong())
            val data = bytearray(length)
            // 从映射区域中读取数据
            mappedbytebuffer[data]
            return data
        } catch (e: exception) {
            e.printstacktrace()
            return null
        } finally {
            if (randomaccessfile != null) {
                try {
                    randomaccessfile.close()
                } catch (e: exception) {
                    e.printstacktrace()
                }
            }
        }
    }

2.2、分段下载关键代码

                val folder = file(download_folder_path)
                            if (!folder.exists()) {
                                folder.mkdirs()
                            }
                            val filename = getfilenamewithpath(filepath)
                            val downfile = file(download_folder_path + file.separator + filename)
                            if (!downfile.exists()) {
                                downfile.createnewfile()
                            }
                            // 使用输入流保存响应体到文件,这里通常是通过http请求,返回的文件流,替换即可
                            val inputstream = body.bytestream()
                            val rw = randomaccessfile(downfile, "rw")
                            rw.seek(startposition)//文件写入的初始位置
                            var hasreads = 0
                            var readlenght: long = 0
                            val bytes = bytearray(4096)
                            while ((inputstream.read(bytes).also { hasreads = it }) > 0) {
                                rw.write(bytes, 0, hasreads)
                                readlenght += hasreads
                                // val l = (readlenght * 100 / contentlength) as int 单块文件写入进度
                            }
                            // 关闭文件输出流和输入流
                            inputstream.close()
                            rw.close()
    /**
     * 根据文件路径获取文件名
     */
    fun getfilenamewithpath(path: string): string {
        if (textutils.isempty(path)) {
            return ""
        }
        val start = path.lastindexof("/")
        return if (start != -1) {
            path.substring(start + 1)
        } else {
            "default_name"
        }
    }

到此这篇关于android 文件分段上传和下载实现方案的文章就介绍到这了,更多相关android 文件分段上传和下载内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com