KNET oferuje wygodne API do uploadu i downloadu plików z progress tracking.
import rip.nerd.kitsunenet.upload.KNETUploader
val uploader = KNETUploader(client)
// Prosty upload
val response = uploader.upload(
url = "https://api.example.com/upload",
file = File("/path/to/file.jpg"),
fieldName = "image"
)
// Z progress
uploader.uploadWithProgress(
url = "https://api.example.com/upload",
file = file,
onProgress = { sent, total ->
val percent = (sent * 100 / total).toInt()
updateProgressBar(percent)
}
)
val response = uploader.multipart(
url = "https://api.example.com/upload",
parts = mapOf(
"title" to "My Photo",
"description" to "Vacation photo",
"tags" to "summer,beach"
),
files = mapOf(
"image" to file,
"thumbnail" to thumbnailFile
)
)
// Z progress dla każdego pliku
uploader.multipartWithProgress(
url = url,
parts = metadata,
files = files,
onProgress = { fileName, sent, total ->
Log.d("Upload", "$fileName: $sent/$total")
}
)
// Z ByteArray
val imageBytes = bitmap.toByteArray()
val response = uploader.upload(
url = url,
data = imageBytes,
fileName = "image.jpg",
mimeType = "image/jpeg"
)
// Z InputStream
val inputStream = contentResolver.openInputStream(uri)!!
val response = uploader.upload(
url = url,
inputStream = inputStream,
fileName = "document.pdf",
mimeType = "application/pdf"
)
import rip.nerd.kitsunenet.download.KNETDownloader
val downloader = KNETDownloader(client)
// Prosty download
val file = downloader.download(
url = "https://example.com/file.zip",
destination = File(context.cacheDir, "file.zip")
)
// Z progress
downloader.downloadWithProgress(
url = url,
destination = destinationFile,
onProgress = { downloaded, total ->
val percent = if (total > 0) (downloaded * 100 / total).toInt() else -1
updateProgress(percent)
}
)
val downloader = KNETDownloader(client)
// Wspiera Range requests
val result = downloader.downloadResumable(
url = url,
destination = file,
onProgress = { downloaded, total, resumed ->
if (resumed) {
Log.d("Download", "Resumed from $downloaded")
}
updateProgress(downloaded, total)
}
)
// Jeśli połączenie zostało przerwane, następne wywołanie
// kontynuuje od miejsca przerwania
val result = downloader.downloadWithRetry(
url = url,
destination = file,
maxRetries = 3,
onRetry = { attempt, error ->
Log.w("Download", "Retry $attempt: ${error.message}")
},
onProgress = { downloaded, total ->
updateProgress(downloaded, total)
}
)
val files = listOf(
"https://example.com/file1.jpg" to File(cacheDir, "file1.jpg"),
"https://example.com/file2.jpg" to File(cacheDir, "file2.jpg"),
"https://example.com/file3.jpg" to File(cacheDir, "file3.jpg")
)
val results = downloader.downloadAll(
files = files,
maxConcurrent = 3,
onProgress = { completed, total ->
Log.d("Batch", "Downloaded $completed/$total files")
}
)
results.forEach { (url, result) ->
when (result) {
is DownloadResult.Success -> Log.d("Download", "OK: $url")
is DownloadResult.Error -> Log.e("Download", "Failed: $url - ${result.error}")
}
}
// Download jako ByteArray (małe pliki)
val bytes = downloader.downloadToMemory(url)
val bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
// Download jako String
val text = downloader.downloadToString(url)
println(text)
class FileTransferViewModel : ViewModel() {
private val uploader = KNETUploader(client)
private val downloader = KNETDownloader(client)
private val _uploadProgress = MutableStateFlow(0f)
val uploadProgress = _uploadProgress.asStateFlow()
private val _downloadProgress = MutableStateFlow(0f)
val downloadProgress = _downloadProgress.asStateFlow()
fun uploadFile(file: File) {
viewModelScope.launch {
_uploadProgress.value = 0f
try {
uploader.uploadWithProgress(
url = "$baseUrl/upload",
file = file,
onProgress = { sent, total ->
_uploadProgress.value = sent.toFloat() / total
}
)
showSuccess("Plik wysłany!")
} catch (e: Exception) {
showError("Błąd uploadu: ${e.message}")
}
}
}
fun downloadFile(url: String, destination: File) {
viewModelScope.launch {
_downloadProgress.value = 0f
try {
downloader.downloadWithProgress(
url = url,
destination = destination,
onProgress = { downloaded, total ->
_downloadProgress.value = if (total > 0) {
downloaded.toFloat() / total
} else 0f
}
)
showSuccess("Plik pobrany!")
} catch (e: Exception) {
showError("Błąd downloadu: ${e.message}")
}
}
}
}
// Upload z Content URI (np. z galerii)
fun uploadFromUri(uri: Uri) {
val contentResolver = context.contentResolver
// Pobierz dane
val inputStream = contentResolver.openInputStream(uri)!!
val mimeType = contentResolver.getType(uri) ?: "application/octet-stream"
val fileName = getFileNameFromUri(uri) ?: "file"
uploader.upload(
url = uploadUrl,
inputStream = inputStream,
fileName = fileName,
mimeType = mimeType
)
}
private fun getFileNameFromUri(uri: Uri): String? {
return contentResolver.query(uri, null, null, null, null)?.use { cursor ->
val index = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
cursor.moveToFirst()
cursor.getString(index)
}
}