mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-11-10 19:26:49 +01:00
stream file to calculate both hash and size without loading it all at once
This commit is contained in:
@@ -36,7 +36,6 @@ import com.vitorpamplona.quartz.nip01Core.core.toHexKey
|
|||||||
import com.vitorpamplona.quartz.nipB7Blossom.BlossomAuthorizationEvent
|
import com.vitorpamplona.quartz.nipB7Blossom.BlossomAuthorizationEvent
|
||||||
import com.vitorpamplona.quartz.nipB7Blossom.BlossomUploadResult
|
import com.vitorpamplona.quartz.nipB7Blossom.BlossomUploadResult
|
||||||
import com.vitorpamplona.quartz.utils.RandomInstance
|
import com.vitorpamplona.quartz.utils.RandomInstance
|
||||||
import com.vitorpamplona.quartz.utils.sha256.sha256
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import okhttp3.MediaType.Companion.toMediaType
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
@@ -48,9 +47,34 @@ import okio.BufferedSink
|
|||||||
import okio.source
|
import okio.source
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
|
import java.security.MessageDigest
|
||||||
import java.util.Base64
|
import java.util.Base64
|
||||||
|
|
||||||
class BlossomUploader {
|
class BlossomUploader {
|
||||||
|
data class StreamInfo(
|
||||||
|
val hash: HexKey,
|
||||||
|
val size: Long,
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate SHA256 hash and size of a file by streaming it in chunks
|
||||||
|
* to avoid loading the entire file into memory.
|
||||||
|
*/
|
||||||
|
private fun calculateHashAndSize(inputStream: InputStream): StreamInfo {
|
||||||
|
val digest = MessageDigest.getInstance("SHA-256")
|
||||||
|
val buffer = ByteArray(8192) // 8KB buffer
|
||||||
|
var bytesRead: Int
|
||||||
|
var totalBytes = 0L
|
||||||
|
|
||||||
|
while (inputStream.read(buffer).also { bytesRead = it } != -1) {
|
||||||
|
digest.update(buffer, 0, bytesRead)
|
||||||
|
totalBytes += bytesRead
|
||||||
|
}
|
||||||
|
|
||||||
|
val hash = digest.digest().toHexKey()
|
||||||
|
return StreamInfo(hash, totalBytes)
|
||||||
|
}
|
||||||
|
|
||||||
fun Context.getFileName(uri: Uri): String? =
|
fun Context.getFileName(uri: Uri): String? =
|
||||||
when (uri.scheme) {
|
when (uri.scheme) {
|
||||||
ContentResolver.SCHEME_CONTENT -> getContentFileName(uri)
|
ContentResolver.SCHEME_CONTENT -> getContentFileName(uri)
|
||||||
@@ -82,25 +106,24 @@ class BlossomUploader {
|
|||||||
val myContentType = contentType ?: contentResolver.getType(uri)
|
val myContentType = contentType ?: contentResolver.getType(uri)
|
||||||
val fileName = context.getFileName(uri)
|
val fileName = context.getFileName(uri)
|
||||||
|
|
||||||
|
// Calculate hash and size by streaming the file in chunks
|
||||||
|
// to avoid loading the entire file into memory
|
||||||
val imageInputStreamForHash = contentResolver.openInputStream(uri)
|
val imageInputStreamForHash = contentResolver.openInputStream(uri)
|
||||||
val payload =
|
checkNotNull(imageInputStreamForHash) { "Can't open the image input stream" }
|
||||||
imageInputStreamForHash?.use {
|
|
||||||
it.readBytes()
|
val streamInfo =
|
||||||
|
imageInputStreamForHash.use {
|
||||||
|
calculateHashAndSize(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
checkNotNull(payload) { "Can't open the image input stream" }
|
|
||||||
|
|
||||||
val hash = sha256(payload).toHexKey()
|
|
||||||
|
|
||||||
val imageInputStream = contentResolver.openInputStream(uri)
|
val imageInputStream = contentResolver.openInputStream(uri)
|
||||||
|
|
||||||
checkNotNull(imageInputStream) { "Can't open the image input stream" }
|
checkNotNull(imageInputStream) { "Can't open the image input stream" }
|
||||||
|
|
||||||
return imageInputStream.use { stream ->
|
return imageInputStream.use { stream ->
|
||||||
upload(
|
upload(
|
||||||
stream,
|
stream,
|
||||||
hash,
|
streamInfo.hash,
|
||||||
payload.size,
|
streamInfo.size.toInt(),
|
||||||
fileName,
|
fileName,
|
||||||
myContentType,
|
myContentType,
|
||||||
alt,
|
alt,
|
||||||
|
|||||||
Reference in New Issue
Block a user