Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b2ea0c7960 | ||
|
|
058bf23465 |
@@ -26,8 +26,8 @@ android {
|
||||
applicationId "com.example.androidbackupgui"
|
||||
minSdk 24
|
||||
targetSdk 34
|
||||
versionCode 9
|
||||
versionName "1.8"
|
||||
versionCode 11
|
||||
versionName "1.10"
|
||||
}
|
||||
buildFeatures {
|
||||
viewBinding true
|
||||
|
||||
@@ -113,9 +113,29 @@ class ResticRestBridge(
|
||||
val started = System.currentTimeMillis()
|
||||
return try {
|
||||
val tmpFile = File(tmpDir, "restic_blob_${UUID.randomUUID()}")
|
||||
val contentLength = session.headers["content-length"]?.toLongOrNull() ?: -1L
|
||||
val input = (session as NanoHTTPD.HTTPSession).inputStream
|
||||
Log.d(TAG, "streamBodyToFile: reading body...")
|
||||
tmpFile.outputStream().use { output -> input.copyTo(output) }
|
||||
Log.d(TAG, "streamBodyToFile: reading body (content-length=$contentLength)...")
|
||||
tmpFile.outputStream().use { output ->
|
||||
if (contentLength > 0) {
|
||||
// Read exactly Content-Length bytes to avoid blocking on keep-alive
|
||||
val buf = ByteArray(8192)
|
||||
var remaining = contentLength
|
||||
while (remaining > 0) {
|
||||
val toRead = minOf(buf.size.toLong(), remaining).toInt()
|
||||
val n = input.read(buf, 0, toRead)
|
||||
if (n == -1) break
|
||||
output.write(buf, 0, n)
|
||||
remaining -= n
|
||||
}
|
||||
if (remaining > 0) {
|
||||
Log.w(TAG, "streamBodyToFile: body truncated, expected $contentLength bytes but got EOF after ${contentLength - remaining}")
|
||||
}
|
||||
Unit
|
||||
} else {
|
||||
input.copyTo(output)
|
||||
}
|
||||
}
|
||||
val elapsed = System.currentTimeMillis() - started
|
||||
val bytes = tmpFile.length()
|
||||
Log.i(TAG, "streamBodyToFile: read $bytes bytes in ${elapsed}ms")
|
||||
@@ -154,7 +174,8 @@ class ResticRestBridge(
|
||||
try {
|
||||
when (transport.download(remotePath, tempFile.absolutePath)) {
|
||||
is AppResult.Success -> {
|
||||
newChunkedResponse(Response.Status.OK, "application/octet-stream", tempFile.inputStream())
|
||||
val data = tempFile.readBytes()
|
||||
newFixedLengthResponse(Response.Status.OK, "application/octet-stream", data.inputStream(), data.size.toLong())
|
||||
}
|
||||
is AppResult.Failure -> newFixedLengthResponse(
|
||||
Response.Status.NOT_FOUND, "text/plain", ""
|
||||
@@ -285,14 +306,14 @@ class ResticRestBridge(
|
||||
response.addHeader("Content-Length", chunkSize.toString())
|
||||
return@runBlocking response
|
||||
}
|
||||
|
||||
// Full file — stream directly without loading into memory
|
||||
// Full file — read into memory (blobs are typically small)
|
||||
val data = tempFile.readBytes()
|
||||
val response = newChunkedResponse(
|
||||
Response.Status.OK,
|
||||
"application/octet-stream",
|
||||
tempFile.inputStream()
|
||||
data.inputStream()
|
||||
)
|
||||
response.addHeader("Content-Length", tempFile.length().toString())
|
||||
response.addHeader("Content-Length", data.size.toString())
|
||||
response
|
||||
}
|
||||
is AppResult.Failure -> newFixedLengthResponse(
|
||||
|
||||
Reference in New Issue
Block a user