[+] Upload
This commit is contained in:
@@ -3,8 +3,10 @@
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:usesCleartextTraffic="true"
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
|
||||
@@ -38,11 +38,13 @@ import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.content.ContextCompat
|
||||
import aza.instant.network.BackendClient
|
||||
import aza.instant.ui.theme.ProjectInstantTheme
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.BufferedReader
|
||||
import java.io.File
|
||||
import java.io.InputStreamReader
|
||||
import java.util.UUID
|
||||
|
||||
class MainActivity : ComponentActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@@ -65,6 +67,7 @@ fun FileListerScreen(modifier: Modifier = Modifier) {
|
||||
var picture by remember { mutableStateOf<Picture?>(null) }
|
||||
val scrollState = rememberScrollState()
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val backendClient = remember { BackendClient() }
|
||||
|
||||
Column(
|
||||
modifier = modifier.fillMaxSize(),
|
||||
@@ -121,16 +124,25 @@ fun FileListerScreen(modifier: Modifier = Modifier) {
|
||||
picture = renderSvgAndroid(context, svg)
|
||||
|
||||
// Save picture to file
|
||||
val file = File(latestImage.parent, "${latestImage.nameWithoutExtension}.framed.${System.currentTimeMillis()}.jpg")
|
||||
file.createNewFile()
|
||||
file.outputStream().use { outputStream ->
|
||||
val renderedImageFile = File(latestImage.parent, "${latestImage.nameWithoutExtension}.framed.${System.currentTimeMillis()}.jpg")
|
||||
renderedImageFile.createNewFile()
|
||||
renderedImageFile.outputStream().use { outputStream ->
|
||||
Bitmap.createBitmap(picture!!).compress(Bitmap.CompressFormat.JPEG, 90, outputStream)
|
||||
}
|
||||
|
||||
feedbackText = "Rendered ${latestImage.name}"
|
||||
feedbackText = "Rendered ${latestImage.name}, now uploading..."
|
||||
|
||||
val response = backendClient.uploadImage(
|
||||
id = UUID.randomUUID().toString(),
|
||||
ownerKey = "1234",
|
||||
originalPhoto = latestImage,
|
||||
editedPhoto = renderedImageFile
|
||||
)
|
||||
feedbackText = "Upload response: ${response.status}"
|
||||
|
||||
} catch (e: Exception) {
|
||||
feedbackText = "Error rendering: ${e.message}"
|
||||
Log.e("MainActivity", "Error rendering", e)
|
||||
feedbackText = "Error during operation: ${e.message}"
|
||||
Log.e("MainActivity", "Error during render or upload", e)
|
||||
}
|
||||
} else {
|
||||
feedbackText = "No images found in CA_IMAGES"
|
||||
@@ -138,7 +150,7 @@ fun FileListerScreen(modifier: Modifier = Modifier) {
|
||||
}
|
||||
},
|
||||
) {
|
||||
Text(text = "Render Latest Image")
|
||||
Text(text = "Render and Upload")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package aza.instant.network
|
||||
|
||||
import io.ktor.client.*
|
||||
import io.ktor.client.engine.cio.*
|
||||
import io.ktor.client.plugins.HttpTimeoutConfig
|
||||
import io.ktor.client.plugins.contentnegotiation.*
|
||||
import io.ktor.client.plugins.timeout
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.client.request.forms.*
|
||||
import io.ktor.client.statement.*
|
||||
import io.ktor.http.*
|
||||
import io.ktor.serialization.kotlinx.json.*
|
||||
import kotlinx.serialization.json.Json
|
||||
import java.io.File
|
||||
|
||||
class BackendClient {
|
||||
|
||||
private val client = HttpClient(CIO) {
|
||||
install(ContentNegotiation) {
|
||||
json(Json {
|
||||
prettyPrint = true
|
||||
isLenient = true
|
||||
ignoreUnknownKeys = true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val API_KEY = "meowmeow"
|
||||
private const val SERVER_URL = "http://172.16.0.212:3000" // For Android emulator
|
||||
}
|
||||
|
||||
suspend fun uploadImage(
|
||||
id: String,
|
||||
ownerKey: String,
|
||||
originalPhoto: File,
|
||||
editedPhoto: File
|
||||
): HttpResponse {
|
||||
val origB = originalPhoto.readBytes()
|
||||
val editB = editedPhoto.readBytes()
|
||||
println(origB.size)
|
||||
println(editB.size)
|
||||
return client.post("$SERVER_URL/upload") {
|
||||
headers {
|
||||
append("x-instant-key", API_KEY)
|
||||
}
|
||||
setBody(
|
||||
MultiPartFormDataContent(
|
||||
formData {
|
||||
append("id", id)
|
||||
append("owner_key", ownerKey)
|
||||
append("\"photo\"", originalPhoto.name, ContentType.Image.JPEG, origB.size.toLong()) { write(origB) }
|
||||
append("\"edited_photo\"", editedPhoto.name, ContentType.Image.JPEG, editB.size.toLong()) { write(editB) }
|
||||
}
|
||||
)
|
||||
)
|
||||
timeout { HttpTimeoutConfig(1 * 60 * 1000L) }
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-2
@@ -72,7 +72,7 @@ async function getExifData(file: File): Promise<any> {
|
||||
const INSTANT_KEY = process.env.INSTANT_KEY!
|
||||
if (!await exists(FOLDER_PHOTOS)) await mkdir(FOLDER_PHOTOS, { recursive: true })
|
||||
|
||||
console.log("Server starting with valid 'secrets.json'.")
|
||||
console.log("Server started.")
|
||||
|
||||
function checkHeaderKey(headers: Record<string, string | undefined>, expectList: string[] = [INSTANT_KEY]) {
|
||||
const key = headers["x-instant-key"]
|
||||
@@ -80,13 +80,16 @@ function checkHeaderKey(headers: Record<string, string | undefined>, expectList:
|
||||
}
|
||||
|
||||
export const app = new Elysia()
|
||||
.get("/", () => "Running!")
|
||||
|
||||
// Error handling: Return status code and message
|
||||
.onError(({ error, status }) => {
|
||||
if (error instanceof HttpError) {
|
||||
if (error.content instanceof String) return status(error.status, { msg: error.message })
|
||||
else return status(error.status, error.content)
|
||||
}
|
||||
else return status(500, { error: "Internal Server Error" })
|
||||
// else return status(500, { error: "Internal Server Error" })
|
||||
else throw error
|
||||
})
|
||||
|
||||
.post("/upload", async ({ body, headers, status }) => {
|
||||
|
||||
Reference in New Issue
Block a user