[Android] Remote access: implement the subtitle upload API endpoint

Nicolas Pomepuy git at videolan.org
Wed Sep 9 06:43:36 UTC 2026


vlc-android | branch: master | Nicolas Pomepuy <nicolas at videolabs.io> | Tue Sep  1 07:50:42 2026 +0200| [49e4d1cdd69cd7bcfdd8b8086f9dd2b8d3104802] | committer: Duncan McNamara

Remote access: implement the subtitle upload API endpoint

> https://code.videolan.org/videolan/vlc-android/commit/49e4d1cdd69cd7bcfdd8b8086f9dd2b8d3104802
---

 .../vlc/remoteaccessserver/RemoteAccessRouting.kt  | 25 ++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/application/remote-access-server/src/main/java/org/videolan/vlc/remoteaccessserver/RemoteAccessRouting.kt b/application/remote-access-server/src/main/java/org/videolan/vlc/remoteaccessserver/RemoteAccessRouting.kt
index 09b2466b23..2056c41477 100644
--- a/application/remote-access-server/src/main/java/org/videolan/vlc/remoteaccessserver/RemoteAccessRouting.kt
+++ b/application/remote-access-server/src/main/java/org/videolan/vlc/remoteaccessserver/RemoteAccessRouting.kt
@@ -248,6 +248,31 @@ fun Route.setupRouting(appContext: Context, scope: CoroutineScope) {
         }
         call.respondText("$fileDescription is uploaded to 'uploads/$fileName'")
     }
+    // Upload a subtitle to the device
+    post("/upload-subtitle") {
+        verifyLogin(settings)
+        var fileName: String
+        val multipartData = call.receiveMultipart()
+
+        multipartData.forEachPart { part ->
+            when (part) {
+                is PartData.FileItem -> {
+                    val uploadDir = File("${AndroidDevices.MediaFolders.EXTERNAL_PUBLIC_DOWNLOAD_DIRECTORY_URI.path}/subtitles")
+                    uploadDir.mkdirs()
+                    fileName = part.originalFileName ?: "subtitle.srt"
+                    val file = File(uploadDir, fileName)
+                    if (file.canonicalFile.parent?.startsWith(uploadDir.absolutePath) != true) {
+                        call.respond(HttpStatusCode.Unauthorized)
+                        throw (IllegalStateException("${file.canonicalFile.parent} is not a valid path"))
+                    }
+                    val fileBytes = part.streamProvider().readBytes()
+                    file.writeBytes(fileBytes)
+                }
+                else -> {}
+            }
+        }
+        call.respond(HttpStatusCode.OK)
+    }
     // Download a log file
     get("/download-logfile") {
         verifyLogin(settings)



More information about the Android mailing list