mirror of
https://github.com/fromchat-messenger/app.git
synced 2026-09-22 19:15:05 +03:00
Implement robust file downloading, uploading and opening
Signed-off-by: denis0001-dev <denis0001.dev@ya.ru>
This commit is contained in:
+17
@@ -12,6 +12,17 @@ internal actual fun expectWriteBytes(path: String, bytes: ByteArray) {
|
||||
file.writeBytes(bytes)
|
||||
}
|
||||
|
||||
internal actual fun expectAppendBytes(path: String, bytes: ByteArray) {
|
||||
val file = File(path)
|
||||
file.parentFile?.mkdirs()
|
||||
file.appendBytes(bytes)
|
||||
}
|
||||
|
||||
internal actual fun expectFileSize(path: String): Long {
|
||||
val file = File(path)
|
||||
return if (file.isFile) file.length() else 0L
|
||||
}
|
||||
|
||||
internal actual fun expectDelete(path: String) {
|
||||
File(path).delete()
|
||||
}
|
||||
@@ -26,6 +37,12 @@ internal actual fun expectDeleteFilesWithPrefix(dirPath: String, namePrefix: Str
|
||||
}
|
||||
}
|
||||
|
||||
internal actual fun expectListFileNamesInDirectory(dirPath: String): List<String> {
|
||||
val dir = File(dirPath)
|
||||
if (!dir.isDirectory) return emptyList()
|
||||
return dir.listFiles()?.map { it.name } ?: emptyList()
|
||||
}
|
||||
|
||||
internal actual fun expectGetAppCacheDirectory(): String =
|
||||
UtilsLibrary.context.cacheDir.absolutePath
|
||||
|
||||
|
||||
+16
@@ -18,6 +18,15 @@ object PlatformFileSystem {
|
||||
expectWriteBytes(path, bytes)
|
||||
}
|
||||
|
||||
/** Appends [bytes] to the file at [path], creating it when missing. */
|
||||
fun appendBytes(path: String, bytes: ByteArray) {
|
||||
if (bytes.isEmpty()) return
|
||||
expectAppendBytes(path, bytes)
|
||||
}
|
||||
|
||||
/** Size in bytes, or 0 when the file does not exist. */
|
||||
fun fileSize(path: String): Long = expectFileSize(path)
|
||||
|
||||
/**
|
||||
* Deletes the file at [path]. No-op if the file does not exist.
|
||||
*/
|
||||
@@ -32,6 +41,10 @@ object PlatformFileSystem {
|
||||
expectDeleteFilesWithPrefix(dirPath, namePrefix)
|
||||
}
|
||||
|
||||
/** Returns filenames (not paths) in [dirPath], or empty if the directory is missing. */
|
||||
fun listFileNamesInDirectory(dirPath: String): List<String> =
|
||||
expectListFileNamesInDirectory(dirPath)
|
||||
|
||||
/**
|
||||
* Returns the platform-specific application cache directory path.
|
||||
* On Android: context.cacheDir (requires UtilsLibrary.init to be called).
|
||||
@@ -51,7 +64,10 @@ object PlatformFileSystem {
|
||||
|
||||
internal expect fun expectExists(path: String): Boolean
|
||||
internal expect fun expectWriteBytes(path: String, bytes: ByteArray)
|
||||
internal expect fun expectAppendBytes(path: String, bytes: ByteArray)
|
||||
internal expect fun expectFileSize(path: String): Long
|
||||
internal expect fun expectDelete(path: String)
|
||||
internal expect fun expectDeleteFilesWithPrefix(dirPath: String, namePrefix: String)
|
||||
internal expect fun expectListFileNamesInDirectory(dirPath: String): List<String>
|
||||
internal expect fun expectGetAppCacheDirectory(): String
|
||||
internal expect fun expectEnsureDirectory(path: String)
|
||||
|
||||
+39
@@ -7,11 +7,18 @@ import kotlinx.cinterop.addressOf
|
||||
import kotlinx.cinterop.usePinned
|
||||
import platform.Foundation.NSData
|
||||
import platform.Foundation.NSFileManager
|
||||
import platform.Foundation.NSNumber
|
||||
import platform.Foundation.NSCachesDirectory
|
||||
import platform.Foundation.NSSearchPathForDirectoriesInDomains
|
||||
import platform.Foundation.NSUserDomainMask
|
||||
import platform.Foundation.create
|
||||
import platform.Foundation.writeToFile
|
||||
import platform.posix.fclose
|
||||
import platform.posix.fopen
|
||||
import platform.posix.fwrite
|
||||
import kotlinx.cinterop.addressOf
|
||||
import kotlinx.cinterop.convert
|
||||
import kotlinx.cinterop.usePinned
|
||||
|
||||
@OptIn(ExperimentalForeignApi::class)
|
||||
internal actual fun expectExists(path: String): Boolean =
|
||||
@@ -29,6 +36,32 @@ internal actual fun expectWriteBytes(path: String, bytes: ByteArray) {
|
||||
nsData?.writeToFile(path, true)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalForeignApi::class)
|
||||
internal actual fun expectAppendBytes(path: String, bytes: ByteArray) {
|
||||
val parent = path.substringBeforeLast('/', missingDelimiterValue = "")
|
||||
if (parent.isNotEmpty()) {
|
||||
NSFileManager.defaultManager.createDirectoryAtPath(parent, true, null, null)
|
||||
}
|
||||
val file = fopen(path, "ab") ?: error("Failed to open file for append")
|
||||
try {
|
||||
bytes.usePinned { pinned ->
|
||||
val written = fwrite(pinned.addressOf(0), 1.convert(), bytes.size.convert(), file).toInt()
|
||||
if (written != bytes.size) {
|
||||
error("Short write")
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
fclose(file)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalForeignApi::class)
|
||||
internal actual fun expectFileSize(path: String): Long {
|
||||
if (!NSFileManager.defaultManager.fileExistsAtPath(path)) return 0L
|
||||
val attrs = NSFileManager.defaultManager.attributesOfItemAtPath(path, null) ?: return 0L
|
||||
return (attrs["NSFileSize"] as? NSNumber)?.longValue ?: 0L
|
||||
}
|
||||
|
||||
internal actual fun expectDelete(path: String) {
|
||||
NSFileManager.defaultManager.removeItemAtPath(path, null)
|
||||
}
|
||||
@@ -43,6 +76,12 @@ internal actual fun expectDeleteFilesWithPrefix(dirPath: String, namePrefix: Str
|
||||
}
|
||||
}
|
||||
|
||||
internal actual fun expectListFileNamesInDirectory(dirPath: String): List<String> {
|
||||
val contents = NSFileManager.defaultManager.contentsOfDirectoryAtPath(dirPath, null)
|
||||
?: return emptyList()
|
||||
return (contents as List<*>).filterIsInstance<String>()
|
||||
}
|
||||
|
||||
internal actual fun expectGetAppCacheDirectory(): String {
|
||||
val paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, true)
|
||||
return (paths.firstOrNull() as? String) ?: ""
|
||||
|
||||
Reference in New Issue
Block a user