Android 文件分段上传和下载实现方案
更新时间:2024年11月22日 14:37:25 作者:粤M温同学
文章介绍了Android大文件下载和上传的分段处理方法,在下载时,使用多线程并发请求文件的多个段,并将这些段写入同一个文件,在上传时,根据文件大小分段上传,每段文件的大小由预设阈值决定,感兴趣的朋友跟随小编一起看看吧
一、背景
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 文件分段上传和下载内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
Android开发之利用ListView动态刷新某个Item
这篇文章主要介绍了Android开发之利用ListView动态刷新某个Item的方法,文章给出了详解的示例代码,相信对大家的理解和学习具有一定的参考借鉴价值,有需要的朋友们下面来一起跟着小编学习学习吧。2016-12-12android开发教程之framework增加字符串资源和图片等resource资源
这篇文章主要介绍了android开发中framework增加字符串资源和图片等resource资源方法,需要的朋友可以参考下2014-02-02Android应用中通过Layout_weight属性用ListView实现表格
这篇文章主要介绍了Android应用中通过Layout_weight属性用ListView实现表格的方法,文中对Layout_weight属性先有一个较为详细的解释,需要的朋友可以参考下2016-04-04
最新评论