在应用程序中,我使用filepicker,通过它我选择文件-〉转换为字节-〉上传到服务器:
private val filesReceiver =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result: ActivityResult ->
if (result.resultCode == Activity.RESULT_OK) {
val data = result.data
data?.let {
val fileUri = data.data!!
var name = ""
var size: Long? = null
fileUri.let { returnUri ->
requireContext().contentResolver.query(returnUri, null, null, null, null)
}?.use { cursor ->
val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
val sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE)
cursor.moveToFirst()
name = cursor.getString(nameIndex)
size = cursor.getLong(sizeIndex)
}
val content = data.data?.let { uri ->
requireContext().contentResolver.openInputStream(uri)
.use { it!!.readBytes() }
}
val fileContent = String(content!!, Charsets.ISO_8859_1)
if (size != null && size!!.toInt() > 0) {
sendingFile(fileContent, name, size!!)
}
}
}
}
它可以很好地处理小文件(〈20 MB)。但是对于大文件(150+ MB),我收到OutOfMemoryException。我在清单中添加了这样的:
android:hardwareAccelerated="true"
android:largeHeap="true"
但它并没有帮助我。我想用途:
fun File.readBytes(): ByteArray
从URI构建文件,但是我得到了关于URI格式的异常。那么,我们有没有什么方法可以像我对小文件一样获得大文件的内容?
更新
此代码用于在聊天中发送文件。因此它可以通过块发送。下面是处理文件内容:
private fun sendingFile(fileContent: String, name: String, size: Long) {
sendingTime = System.currentTimeMillis() / 1000
if (size.toInt() < partSize) {
sendFilePart(0, fileContent, name, size)
} else {
dialog.show()
for (currentPart in 0..size.toInt().div(partSize)) {
val slicedString = fileContent.slice(
currentPart * partSize
until if ((currentPart + 1) * partSize <= fileContent.length) {
(currentPart + 1) * partSize
} else {
fileContent.length
}
)
if (currentPart in 0..size.toInt().div(partSize)) {
dialog.hide()
sendingTime = null
}
sendFilePart(currentPart, slicedString, name, size)
}
}
}
private fun sendFilePart(part: Int?, fileContent: String, fileName: String, fileSize: Long) {
chatVM.mWebSocket.value?.apply {
if (sendingTime == null) {
sendingTime = System.currentTimeMillis() / 1000
}
send(
ChatRequestMessages.sendFilePart(
part!!,
fileContent,
fileName,
fileSize,
sendingTime!!,
chatVM.selectedContact.value?.id!!
)
)
}
}
这里块大小是private val partSize = 10000
。
2条答案
按热度按时间polhcujo1#
如果你使用OkHttp上传文件,你可以简单地使用Uri创建请求体,以避免将整个文件内容读入内存:
来源:https://cketti.de/2020/05/23/content-uris-and-okhttp/
n1bvdmb62#
因此,经过一些研究,我设法找到了解决方案。由于事实上,我发送的文件块,所以我这样做的方法:
下面是选择后的文件处理:
有时它可以冻结用户界面,但一般来说,它的工作。