# 百度网盘分片上传文件
在请求百度网盘文件上传api接口时,如果单个文件大于4M就需要分片上传
文件分片,代码如下:
@Throws(IOException::class)
fun splitFile(path: String?): MutableList<File> {
if (!File(
Environment.getExternalStorageDirectory().absolutePath
.toString() + "/.UploadTmp"
).exists()
) {
File(
Environment.getExternalStorageDirectory().absolutePath
.toString() + "/.UploadTmp"
).mkdirs()
}
var list: MutableList<File> = ArrayList()
val `is`: InputStream = FileInputStream(path)
var len = 0
val buff = ByteArray(PART_SIZE)
var i = 1
while (`is`.read(buff).also { len = it } != -1) {
val filePath: String = Environment.getExternalStorageDirectory().getAbsolutePath()
.toString() + "/.UploadTmp/file" + i + ".tmp"
val raf = RandomAccessFile(filePath, "rw")
raf.write(buff, 0, len)
raf.close()
list.add(File(filePath))
i++
}
`is`.close()
return list
}
分片后的文件保存到 Environment.getExternalStorageDirectory().absolutePath
.toString() + “/.UploadTmp” 目录下。
上传文件后记得删除分片的文件哦,不然会占用不必要的存储空间。
使用retrofit+okhttp+rxjava实现网络请求
需要导入依赖的包就自行导入,这里不做解释
首先需要创建一个接口,在接口中的用于上传分片的代码如下:
@Multipart
@POST("rest/2.0/pcs/superfile2?method=upload")
@Headers("accept: */*")
fun upload(
@Query("access_token") accessToken: String,
@Query("type") type: String,
@Query("path") path: String,
@Query("uploadid") uploadid: String,
@Query("partseq") partseq: Int,
@Part file:MultipartBody.Part
): Observable<UploadModel> //UploadModel类,自行参考百度网盘返回的数据,生成的一个类
需要创建一个用于初始化网络请求的类:
object NetWorkUtil {
const val TAG = "NetWorkUtil"
private val gson = GsonBuilder().setLenient().create()
private const val host2 = "https://d.pcs.baidu.com/"
private const val dataParse = "multipart/form-data"
private var accessToken = "" //自己授权后获得的token,这里就解释了,不会的去百度网盘开发者文档查看
private val server: NcServer
init {
val client = OkHttpClient.Builder()
val retrofit = Retrofit.Builder()
.baseUrl(host2)
.client(client.build())
.addCallAdapterFactory(RxJava2CallAdapterFactory.createAsync())
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
server = retrofit.create(NcServer::class.java)
}
/**
* 分片上传
* @param path 上传后使用的文件绝对路径,需要urlencode
* @param uploadid precreate接口下发的uploadid
* @param partseq 文件分片的位置序号,从0开始,参考precreate接口返回的block_list
* @param file 上传的文件内容
*/
fun upload(
context: Context,
path: String,
uploadid: String,
partseq: Int,
file: File
) {
accessToken = SPUtils.get(context, "access_token", "") as String
//以表单的方式上传文件
val map: MutableMap<String, RequestBody> = HashMap()
val requestFile = RequestBody.create(
MediaType.parse(dataParse),
file
)
map["file"] = requestFile
val createFormData = MultipartBody.Part.createFormData("file", path, requestFile)
server.upload(
accessToken,
"tmpfile",
path,
uploadid,
partseq,
createFormData
)
.subscribeOn(Schedulers.io())//被观察者
.observeOn(AndroidSchedulers.mainThread())//响应端
.subscribeBy(
onNext = {
//请求接口成功,在此处理
},
onError = {
//请求返回异常,在此处理
}
)
}
}
使用方式:
调用上面的splitFile(path: String?)方法获取文件分片后的文件列表,然后再调用 upload()方法进行网络请求上传文件