Skip to content

Commit 9a36431

Browse files
Merge pull request #472 from appwrite/feat-kt-input-file
Add android input file
2 parents 53481c8 + c28895d commit 9a36431

File tree

17 files changed

+241
-30
lines changed

17 files changed

+241
-30
lines changed

src/SDK/Language/Android.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,11 @@ public function getFiles()
131131
'destination' => '/library/src/main/java/{{ sdk.namespace | caseSlash }}/json/PreciseNumberAdapter.kt',
132132
'template' => '/android/library/src/main/java/io/appwrite/json/PreciseNumberAdapter.kt.twig',
133133
],
134+
[
135+
'scope' => 'default',
136+
'destination' => '/library/src/main/java/{{ sdk.namespace | caseSlash }}/models/InputFile.kt',
137+
'template' => '/android/library/src/main/java/io/appwrite/models/InputFile.kt.twig',
138+
],
134139
[
135140
'scope' => 'default',
136141
'destination' => '/library/src/main/java/{{ sdk.namespace | caseSlash }}/models/RealtimeModels.kt',

src/SDK/Language/Kotlin.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ public function getTypeName($type)
111111
case self::TYPE_STRING:
112112
return 'String';
113113
case self::TYPE_FILE:
114-
return 'File';
114+
return 'InputFile';
115115
case self::TYPE_BOOLEAN:
116116
return 'Boolean';
117117
case self::TYPE_ARRAY:
@@ -197,7 +197,7 @@ public function getParamExample(array $param)
197197
if(empty($example) && $example !== 0 && $example !== false) {
198198
switch ($type) {
199199
case self::TYPE_FILE:
200-
$output .= 'File("file.png")';
200+
$output .= 'InputFile.fromPath("file.png")';
201201
break;
202202
case self::TYPE_NUMBER:
203203
case self::TYPE_INTEGER:
@@ -390,6 +390,12 @@ public function getFiles()
390390
'template' => '/kotlin/src/main/kotlin/io/appwrite/services/ServiceTemplate.kt.twig',
391391
'minify' => false,
392392
],
393+
[
394+
'scope' => 'default',
395+
'destination' => '/src/main/kotlin/{{ sdk.namespace | caseSlash }}/models/InputFile.kt',
396+
'template' => '/kotlin/src/main/kotlin/io/appwrite/models/InputFile.kt.twig',
397+
'minify' => false,
398+
],
393399
[
394400
'scope' => 'default',
395401
'destination' => '/src/main/kotlin/{{ sdk.namespace | caseSlash }}/models/UploadProgress.kt',

templates/android/library/src/main/java/io/appwrite/Client.kt.twig

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {{ sdk.namespace | caseDot }}.cookies.stores.SharedPreferencesCookieStore
99
import {{ sdk.namespace | caseDot }}.exceptions.{{ spec.title | caseUcfirst }}Exception
1010
import {{ sdk.namespace | caseDot }}.extensions.fromJson
1111
import {{ sdk.namespace | caseDot }}.json.PreciseNumberAdapter
12+
import {{ sdk.namespace | caseDot }}.models.InputFile
1213
import {{ sdk.namespace | caseDot }}.models.UploadProgress
1314
import kotlinx.coroutines.CoroutineScope
1415
import kotlinx.coroutines.Dispatchers
@@ -322,14 +323,29 @@ class Client @JvmOverloads constructor(
322323
idParamName: String? = null,
323324
onProgress: ((UploadProgress) -> Unit)? = null,
324325
): T {
325-
val file = params[paramName] as File
326-
val size = file.length()
326+
var file: RandomAccessFile? = null
327+
val input = params[paramName] as InputFile
328+
val size: Long = when(input.sourceType) {
329+
"path", "file" -> {
330+
file = RandomAccessFile(input.path, "r")
331+
file.length()
332+
}
333+
"bytes" -> {
334+
(input.data as ByteArray).size.toLong()
335+
}
336+
else -> throw UnsupportedOperationException()
337+
}
327338

328339
if (size < CHUNK_SIZE) {
340+
val data = when(input.sourceType) {
341+
"file", "path" -> File(input.path).asRequestBody()
342+
"bytes" -> (input.data as ByteArray).toRequestBody(input.mimeType.toMediaType())
343+
else -> throw UnsupportedOperationException()
344+
}
329345
params[paramName] = MultipartBody.Part.createFormData(
330346
paramName,
331-
file.name,
332-
file.asRequestBody()
347+
input.filename,
348+
data
333349
)
334350
return call(
335351
method = "POST",
@@ -341,7 +357,6 @@ class Client @JvmOverloads constructor(
341357
)
342358
}
343359

344-
val input = RandomAccessFile(file, "r")
345360
val buffer = ByteArray(CHUNK_SIZE)
346361
var offset = 0L
347362
var result: Map<*, *>? = null
@@ -360,12 +375,29 @@ class Client @JvmOverloads constructor(
360375
}
361376

362377
while (offset < size) {
363-
input.seek(offset)
364-
input.read(buffer)
378+
when(input.sourceType) {
379+
"file", "path" -> {
380+
file!!.seek(offset)
381+
file!!.read(buffer)
382+
}
383+
"bytes" -> {
384+
val end = if (offset + CHUNK_SIZE < size) {
385+
offset + CHUNK_SIZE
386+
} else {
387+
size - 1
388+
}
389+
(input.data as ByteArray).copyInto(
390+
buffer,
391+
startIndex = offset.toInt(),
392+
endIndex = end.toInt()
393+
)
394+
}
395+
else -> throw UnsupportedOperationException()
396+
}
365397

366398
params[paramName] = MultipartBody.Part.createFormData(
367399
paramName,
368-
file.name,
400+
input.filename,
369401
buffer.toRequestBody()
370402
)
371403

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package {{ sdk.namespace | caseDot }}.models
2+
3+
import java.io.File
4+
import java.net.URLConnection
5+
import java.nio.file.Files
6+
import java.nio.file.Paths
7+
8+
class InputFile private constructor() {
9+
10+
lateinit var path: String
11+
lateinit var filename: String
12+
lateinit var mimeType: String
13+
lateinit var sourceType: String
14+
lateinit var data: Any
15+
16+
companion object {
17+
fun fromFile(file: File) = InputFile().apply {
18+
path = file.canonicalPath
19+
filename = file.name
20+
mimeType = Files.probeContentType(Paths.get(file.canonicalPath))
21+
?: URLConnection.guessContentTypeFromName(filename)
22+
?: ""
23+
sourceType = "file"
24+
}
25+
26+
fun fromPath(path: String): InputFile = fromFile(File(path)).apply {
27+
sourceType = "path"
28+
}
29+
30+
fun fromBytes(bytes: ByteArray, filename: String = "", mimeType: String = "") = InputFile().apply {
31+
this.filename = filename
32+
this.mimeType = mimeType
33+
data = bytes
34+
sourceType = "bytes"
35+
}
36+
}
37+
}

templates/kotlin/src/main/kotlin/io/appwrite/Client.kt.twig

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import com.google.gson.reflect.TypeToken
55
import {{ sdk.namespace | caseDot }}.exceptions.{{ spec.title | caseUcfirst }}Exception
66
import {{ sdk.namespace | caseDot }}.extensions.fromJson
77
import {{ sdk.namespace | caseDot }}.json.PreciseNumberAdapter
8+
import {{ sdk.namespace | caseDot }}.models.InputFile
89
import {{ sdk.namespace | caseDot }}.models.UploadProgress
910
import kotlinx.coroutines.CoroutineScope
1011
import kotlinx.coroutines.Dispatchers
@@ -281,14 +282,29 @@ class Client @JvmOverloads constructor(
281282
idParamName: String? = null,
282283
onProgress: ((UploadProgress) -> Unit)? = null,
283284
): T {
284-
val file = params[paramName] as File
285-
val size = file.length()
285+
var file: RandomAccessFile? = null
286+
val input = params[paramName] as InputFile
287+
val size: Long = when(input.sourceType) {
288+
"path", "file" -> {
289+
file = RandomAccessFile(input.path, "r")
290+
file.length()
291+
}
292+
"bytes" -> {
293+
(input.data as ByteArray).size.toLong()
294+
}
295+
else -> throw UnsupportedOperationException()
296+
}
286297

287298
if (size < CHUNK_SIZE) {
299+
val data = when(input.sourceType) {
300+
"file", "path" -> File(input.path).asRequestBody()
301+
"bytes" -> (input.data as ByteArray).toRequestBody(input.mimeType.toMediaType())
302+
else -> throw UnsupportedOperationException()
303+
}
288304
params[paramName] = MultipartBody.Part.createFormData(
289305
paramName,
290-
file.name,
291-
file.asRequestBody()
306+
input.filename,
307+
data
292308
)
293309
return call(
294310
method = "POST",
@@ -300,7 +316,6 @@ class Client @JvmOverloads constructor(
300316
)
301317
}
302318

303-
val input = RandomAccessFile(file, "r")
304319
val buffer = ByteArray(CHUNK_SIZE)
305320
var offset = 0L
306321
var result: Map<*, *>? = null
@@ -319,12 +334,29 @@ class Client @JvmOverloads constructor(
319334
}
320335

321336
while (offset < size) {
322-
input.seek(offset)
323-
input.read(buffer)
337+
when(input.sourceType) {
338+
"file", "path" -> {
339+
file!!.seek(offset)
340+
file!!.read(buffer)
341+
}
342+
"bytes" -> {
343+
val end = if (offset + CHUNK_SIZE < size) {
344+
offset + CHUNK_SIZE
345+
} else {
346+
size - 1
347+
}
348+
(input.data as ByteArray).copyInto(
349+
buffer,
350+
startIndex = offset.toInt(),
351+
endIndex = end.toInt()
352+
)
353+
}
354+
else -> throw UnsupportedOperationException()
355+
}
324356

325357
params[paramName] = MultipartBody.Part.createFormData(
326358
paramName,
327-
file.name,
359+
input.filename,
328360
buffer.toRequestBody()
329361
)
330362

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package {{ sdk.namespace | caseDot }}.models
2+
3+
import java.io.File
4+
import java.net.URLConnection
5+
import java.nio.file.Files
6+
import java.nio.file.Paths
7+
8+
class InputFile private constructor() {
9+
10+
lateinit var path: String
11+
lateinit var filename: String
12+
lateinit var mimeType: String
13+
lateinit var sourceType: String
14+
lateinit var data: Any
15+
16+
companion object {
17+
fun fromFile(file: File) = InputFile().apply {
18+
path = file.canonicalPath
19+
filename = file.name
20+
mimeType = Files.probeContentType(Paths.get(file.canonicalPath))
21+
?: URLConnection.guessContentTypeFromName(filename)
22+
?: ""
23+
sourceType = "file"
24+
}
25+
26+
fun fromPath(path: String): InputFile = fromFile(File(path)).apply {
27+
sourceType = "path"
28+
}
29+
30+
fun fromBytes(bytes: ByteArray, filename: String = "", mimeType: String = "") = InputFile().apply {
31+
this.filename = filename
32+
this.mimeType = mimeType
33+
data = bytes
34+
sourceType = "bytes"
35+
}
36+
}
37+
}

tests/Android11Java11Test.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ class Android11Java11Test extends Base
1919
...Base::BAR_RESPONSES,
2020
...Base::GENERAL_RESPONSES,
2121
...Base::LARGE_FILE_RESPONSES,
22+
...Base::LARGE_FILE_RESPONSES,
23+
...Base::LARGE_FILE_RESPONSES,
2224
...Base::EXCEPTION_RESPONSES,
2325
...Base::REALTIME_RESPONSES,
2426
...Base::COOKIE_RESPONSES,

tests/Android11Java8Test.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ class Android11Java8Test extends Base
1919
...Base::BAR_RESPONSES,
2020
...Base::GENERAL_RESPONSES,
2121
...Base::LARGE_FILE_RESPONSES,
22+
...Base::LARGE_FILE_RESPONSES,
23+
...Base::LARGE_FILE_RESPONSES,
2224
...Base::EXCEPTION_RESPONSES,
2325
...Base::REALTIME_RESPONSES,
2426
...Base::COOKIE_RESPONSES,

tests/Android12Java11Test.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ class Android12Java11Test extends Base
1919
...Base::BAR_RESPONSES,
2020
...Base::GENERAL_RESPONSES,
2121
...Base::LARGE_FILE_RESPONSES,
22+
...Base::LARGE_FILE_RESPONSES,
23+
...Base::LARGE_FILE_RESPONSES,
2224
...Base::EXCEPTION_RESPONSES,
2325
...Base::REALTIME_RESPONSES,
2426
...Base::COOKIE_RESPONSES,

tests/Android12Java8Test.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ class Android12Java8Test extends Base
1919
...Base::BAR_RESPONSES,
2020
...Base::GENERAL_RESPONSES,
2121
...Base::LARGE_FILE_RESPONSES,
22+
...Base::LARGE_FILE_RESPONSES,
23+
...Base::LARGE_FILE_RESPONSES,
2224
...Base::EXCEPTION_RESPONSES,
2325
...Base::REALTIME_RESPONSES,
2426
...Base::COOKIE_RESPONSES,

0 commit comments

Comments
 (0)