@simplysm/capacitor-plugin-file-system 13.0.99 → 14.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +1 -0
- package/android/src/main/kotlin/kr/co/simplysm/capacitor/filesystem/FileSystemPlugin.kt +306 -0
- package/android/src/main/kotlin/kr/co/simplysm/capacitor/filesystem/FileSystemProvider.kt +5 -0
- package/dist/FileSystem.d.ts +24 -24
- package/dist/FileSystem.js +103 -97
- package/dist/FileSystem.js.map +1 -6
- package/dist/FileSystemPlugin.js +2 -1
- package/dist/FileSystemPlugin.js.map +1 -6
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -6
- package/dist/web/FileSystemWeb.d.ts +3 -3
- package/dist/web/FileSystemWeb.js +64 -64
- package/dist/web/FileSystemWeb.js.map +1 -6
- package/dist/web/VirtualFileSystem.d.ts +6 -6
- package/dist/web/VirtualFileSystem.js +33 -36
- package/dist/web/VirtualFileSystem.js.map +1 -6
- package/package.json +6 -6
- package/src/FileSystem.ts +25 -25
- package/src/index.ts +1 -1
- package/src/web/FileSystemWeb.ts +7 -7
- package/src/web/VirtualFileSystem.ts +6 -6
- package/README.md +0 -98
- package/android/src/main/java/kr/co/simplysm/capacitor/filesystem/FileSystemPlugin.java +0 -305
- package/android/src/main/java/kr/co/simplysm/capacitor/filesystem/FileSystemProvider.java +0 -6
package/android/build.gradle
CHANGED
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
package kr.co.simplysm.capacitor.filesystem
|
|
2
|
+
|
|
3
|
+
import android.Manifest
|
|
4
|
+
import android.content.Intent
|
|
5
|
+
import android.content.pm.PackageManager
|
|
6
|
+
import android.net.Uri
|
|
7
|
+
import android.os.Build
|
|
8
|
+
import android.os.Environment
|
|
9
|
+
import android.provider.Settings
|
|
10
|
+
import android.util.Base64
|
|
11
|
+
import android.util.Log
|
|
12
|
+
import androidx.core.app.ActivityCompat
|
|
13
|
+
import androidx.core.content.ContextCompat
|
|
14
|
+
import androidx.core.content.FileProvider
|
|
15
|
+
import com.getcapacitor.JSArray
|
|
16
|
+
import com.getcapacitor.JSObject
|
|
17
|
+
import com.getcapacitor.Plugin
|
|
18
|
+
import com.getcapacitor.PluginCall
|
|
19
|
+
import com.getcapacitor.PluginMethod
|
|
20
|
+
import com.getcapacitor.annotation.CapacitorPlugin
|
|
21
|
+
import java.io.BufferedInputStream
|
|
22
|
+
import java.io.BufferedOutputStream
|
|
23
|
+
import java.io.ByteArrayOutputStream
|
|
24
|
+
import java.io.File
|
|
25
|
+
import java.io.FileInputStream
|
|
26
|
+
import java.io.FileOutputStream
|
|
27
|
+
import java.nio.charset.StandardCharsets
|
|
28
|
+
|
|
29
|
+
@CapacitorPlugin(name = "FileSystem")
|
|
30
|
+
class FileSystemPlugin : Plugin() {
|
|
31
|
+
|
|
32
|
+
companion object {
|
|
33
|
+
private const val TAG = "FileSystemPlugin"
|
|
34
|
+
private const val PERMISSION_REQUEST_CODE = 1001
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@PluginMethod
|
|
38
|
+
fun checkPermissions(call: PluginCall) {
|
|
39
|
+
val granted = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
|
40
|
+
Environment.isExternalStorageManager()
|
|
41
|
+
} else {
|
|
42
|
+
val ctx = context
|
|
43
|
+
ContextCompat.checkSelfPermission(ctx, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
|
|
44
|
+
&& ContextCompat.checkSelfPermission(ctx, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
|
|
45
|
+
}
|
|
46
|
+
val ret = JSObject()
|
|
47
|
+
ret.put("granted", granted)
|
|
48
|
+
call.resolve(ret)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@PluginMethod
|
|
52
|
+
fun requestPermissions(call: PluginCall) {
|
|
53
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
|
54
|
+
if (!Environment.isExternalStorageManager()) {
|
|
55
|
+
val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
|
|
56
|
+
intent.data = Uri.parse("package:" + context.packageName)
|
|
57
|
+
activity.startActivity(intent)
|
|
58
|
+
}
|
|
59
|
+
} else {
|
|
60
|
+
val readGranted = ContextCompat.checkSelfPermission(
|
|
61
|
+
context,
|
|
62
|
+
Manifest.permission.READ_EXTERNAL_STORAGE
|
|
63
|
+
) == PackageManager.PERMISSION_GRANTED
|
|
64
|
+
val writeGranted = ContextCompat.checkSelfPermission(
|
|
65
|
+
context,
|
|
66
|
+
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
|
67
|
+
) == PackageManager.PERMISSION_GRANTED
|
|
68
|
+
|
|
69
|
+
if (!readGranted || !writeGranted) {
|
|
70
|
+
ActivityCompat.requestPermissions(
|
|
71
|
+
activity,
|
|
72
|
+
arrayOf(
|
|
73
|
+
Manifest.permission.READ_EXTERNAL_STORAGE,
|
|
74
|
+
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
|
75
|
+
),
|
|
76
|
+
PERMISSION_REQUEST_CODE
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
call.resolve()
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@PluginMethod
|
|
84
|
+
fun readdir(call: PluginCall) {
|
|
85
|
+
val path = call.getString("path")
|
|
86
|
+
if (path == null) {
|
|
87
|
+
call.reject("path is required")
|
|
88
|
+
return
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
val dir = File(path)
|
|
92
|
+
if (!dir.exists() || !dir.isDirectory) {
|
|
93
|
+
call.reject("Directory does not exist")
|
|
94
|
+
return
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
val files = dir.listFiles()
|
|
98
|
+
if (files == null) {
|
|
99
|
+
call.reject("Cannot read directory")
|
|
100
|
+
return
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
val result = JSArray()
|
|
104
|
+
for (f in files) {
|
|
105
|
+
val info = JSObject()
|
|
106
|
+
info.put("name", f.name)
|
|
107
|
+
info.put("isDirectory", f.isDirectory)
|
|
108
|
+
result.put(info)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
val ret = JSObject()
|
|
112
|
+
ret.put("files", result)
|
|
113
|
+
call.resolve(ret)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
@PluginMethod
|
|
117
|
+
fun getStoragePath(call: PluginCall) {
|
|
118
|
+
val type = call.getString("type")
|
|
119
|
+
if (type == null) {
|
|
120
|
+
call.reject("type is required")
|
|
121
|
+
return
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
val ctx = context
|
|
125
|
+
val path: File? = when (type) {
|
|
126
|
+
"external" -> Environment.getExternalStorageDirectory()
|
|
127
|
+
"externalFiles" -> ctx.getExternalFilesDir(null)
|
|
128
|
+
"externalCache" -> ctx.externalCacheDir
|
|
129
|
+
"externalMedia" -> {
|
|
130
|
+
val dirs = ctx.externalMediaDirs
|
|
131
|
+
if (dirs.isNotEmpty()) dirs[0] else null
|
|
132
|
+
}
|
|
133
|
+
"appData" -> File(ctx.applicationInfo.dataDir)
|
|
134
|
+
"appFiles" -> ctx.filesDir
|
|
135
|
+
"appCache" -> ctx.cacheDir
|
|
136
|
+
else -> {
|
|
137
|
+
call.reject("Unknown type: $type")
|
|
138
|
+
return
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (path == null) {
|
|
143
|
+
call.reject("Path not available")
|
|
144
|
+
return
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
val ret = JSObject()
|
|
148
|
+
ret.put("path", path.absolutePath)
|
|
149
|
+
call.resolve(ret)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
@PluginMethod
|
|
153
|
+
fun getUri(call: PluginCall) {
|
|
154
|
+
val path = call.getString("path")
|
|
155
|
+
if (path == null) {
|
|
156
|
+
call.reject("path is required")
|
|
157
|
+
return
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
try {
|
|
161
|
+
val authority = context.packageName + ".filesystem.provider"
|
|
162
|
+
val uri = FileProvider.getUriForFile(context, authority, File(path))
|
|
163
|
+
val ret = JSObject()
|
|
164
|
+
ret.put("uri", uri.toString())
|
|
165
|
+
call.resolve(ret)
|
|
166
|
+
} catch (e: Exception) {
|
|
167
|
+
Log.e(TAG, "getUri failed", e)
|
|
168
|
+
call.reject("getUri failed: " + e.message)
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
@PluginMethod
|
|
173
|
+
fun writeFile(call: PluginCall) {
|
|
174
|
+
val path = call.getString("path")
|
|
175
|
+
val data = call.getString("data")
|
|
176
|
+
val encoding = call.getString("encoding", "utf8")
|
|
177
|
+
|
|
178
|
+
if (path == null || data == null) {
|
|
179
|
+
call.reject("path and data are required")
|
|
180
|
+
return
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
try {
|
|
184
|
+
val file = File(path)
|
|
185
|
+
val parent = file.parentFile
|
|
186
|
+
if (parent != null && !parent.exists()) {
|
|
187
|
+
parent.mkdirs()
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
val bytes = if ("base64" == encoding) {
|
|
191
|
+
Base64.decode(data, Base64.DEFAULT)
|
|
192
|
+
} else {
|
|
193
|
+
data.toByteArray(StandardCharsets.UTF_8)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
BufferedOutputStream(FileOutputStream(file)).use { bos ->
|
|
197
|
+
bos.write(bytes)
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
call.resolve()
|
|
201
|
+
} catch (e: Exception) {
|
|
202
|
+
Log.e(TAG, "writeFile failed", e)
|
|
203
|
+
call.reject("Write failed: " + e.message)
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
@PluginMethod
|
|
208
|
+
fun readFile(call: PluginCall) {
|
|
209
|
+
val path = call.getString("path")
|
|
210
|
+
val encoding = call.getString("encoding", "utf8")
|
|
211
|
+
|
|
212
|
+
if (path == null) {
|
|
213
|
+
call.reject("path is required")
|
|
214
|
+
return
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
val file = File(path)
|
|
218
|
+
if (!file.exists()) {
|
|
219
|
+
call.reject("File not found: $path")
|
|
220
|
+
return
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
try {
|
|
224
|
+
BufferedInputStream(FileInputStream(file)).use { bis ->
|
|
225
|
+
ByteArrayOutputStream().use { baos ->
|
|
226
|
+
val buf = ByteArray(8192)
|
|
227
|
+
var len: Int
|
|
228
|
+
while (bis.read(buf).also { len = it } != -1) {
|
|
229
|
+
baos.write(buf, 0, len)
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
val result = if ("base64" == encoding) {
|
|
233
|
+
Base64.encodeToString(baos.toByteArray(), Base64.NO_WRAP)
|
|
234
|
+
} else {
|
|
235
|
+
baos.toString("UTF-8")
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
val ret = JSObject()
|
|
239
|
+
ret.put("data", result)
|
|
240
|
+
call.resolve(ret)
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
} catch (e: Exception) {
|
|
244
|
+
Log.e(TAG, "readFile failed", e)
|
|
245
|
+
call.reject("Read failed: " + e.message)
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
@PluginMethod
|
|
250
|
+
fun remove(call: PluginCall) {
|
|
251
|
+
val path = call.getString("path")
|
|
252
|
+
if (path == null) {
|
|
253
|
+
call.reject("path is required")
|
|
254
|
+
return
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (deleteRecursively(File(path))) {
|
|
258
|
+
call.resolve()
|
|
259
|
+
} else {
|
|
260
|
+
call.reject("Delete failed")
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
@PluginMethod
|
|
265
|
+
fun mkdir(call: PluginCall) {
|
|
266
|
+
val path = call.getString("path")
|
|
267
|
+
if (path == null) {
|
|
268
|
+
call.reject("path is required")
|
|
269
|
+
return
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
val dir = File(path)
|
|
273
|
+
if (dir.exists() || dir.mkdirs()) {
|
|
274
|
+
call.resolve()
|
|
275
|
+
} else {
|
|
276
|
+
call.reject("Failed to create directory")
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
@PluginMethod
|
|
281
|
+
fun exists(call: PluginCall) {
|
|
282
|
+
val path = call.getString("path")
|
|
283
|
+
if (path == null) {
|
|
284
|
+
call.reject("path is required")
|
|
285
|
+
return
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
val ret = JSObject()
|
|
289
|
+
ret.put("exists", File(path).exists())
|
|
290
|
+
call.resolve(ret)
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
private fun deleteRecursively(file: File): Boolean {
|
|
294
|
+
if (file.isDirectory) {
|
|
295
|
+
val children = file.listFiles()
|
|
296
|
+
if (children != null) {
|
|
297
|
+
for (child in children) {
|
|
298
|
+
if (!deleteRecursively(child)) {
|
|
299
|
+
return false
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
return file.delete()
|
|
305
|
+
}
|
|
306
|
+
}
|
package/dist/FileSystem.d.ts
CHANGED
|
@@ -1,61 +1,61 @@
|
|
|
1
1
|
import type { FileInfo, StorageType } from "./FileSystemPlugin";
|
|
2
2
|
import type { Bytes } from "@simplysm/core-common";
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
* - Android 11+:
|
|
6
|
-
* - Android 10-: READ/WRITE_EXTERNAL_STORAGE
|
|
7
|
-
* - Browser: IndexedDB
|
|
4
|
+
* 파일 시스템 접근 플러그인
|
|
5
|
+
* - Android 11+: MANAGE_EXTERNAL_STORAGE 권한을 통한 전체 파일 시스템 접근
|
|
6
|
+
* - Android 10-: READ/WRITE_EXTERNAL_STORAGE 권한
|
|
7
|
+
* - Browser: IndexedDB 기반 에뮬레이션
|
|
8
8
|
*/
|
|
9
9
|
export declare abstract class FileSystem {
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
11
|
+
* 권한 확인
|
|
12
12
|
*/
|
|
13
13
|
static checkPermissions(): Promise<boolean>;
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
16
|
-
* - Android 11+:
|
|
17
|
-
* - Android 10-:
|
|
15
|
+
* 권한 요청
|
|
16
|
+
* - Android 11+: 설정 화면으로 이동
|
|
17
|
+
* - Android 10-: 권한 대화상자 표시
|
|
18
18
|
*/
|
|
19
19
|
static requestPermissions(): Promise<void>;
|
|
20
20
|
/**
|
|
21
|
-
*
|
|
21
|
+
* 디렉토리 읽기
|
|
22
22
|
*/
|
|
23
23
|
static readdir(dirPath: string): Promise<FileInfo[]>;
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
26
|
-
* @param type
|
|
27
|
-
* - external:
|
|
28
|
-
* - externalFiles:
|
|
29
|
-
* - externalCache:
|
|
30
|
-
* - externalMedia:
|
|
31
|
-
* - appData:
|
|
32
|
-
* - appFiles:
|
|
33
|
-
* - appCache:
|
|
25
|
+
* 저장소 경로 조회
|
|
26
|
+
* @param type 저장소 유형
|
|
27
|
+
* - external: 외부 저장소 루트 (Environment.getExternalStorageDirectory)
|
|
28
|
+
* - externalFiles: 앱 전용 외부 파일 디렉토리
|
|
29
|
+
* - externalCache: 앱 전용 외부 캐시 디렉토리
|
|
30
|
+
* - externalMedia: 앱 전용 외부 미디어 디렉토리
|
|
31
|
+
* - appData: 앱 데이터 디렉토리
|
|
32
|
+
* - appFiles: 앱 파일 디렉토리
|
|
33
|
+
* - appCache: 앱 캐시 디렉토리
|
|
34
34
|
*/
|
|
35
35
|
static getStoragePath(type: StorageType): Promise<string>;
|
|
36
36
|
/**
|
|
37
|
-
*
|
|
37
|
+
* 파일 URI 조회 (FileProvider)
|
|
38
38
|
*/
|
|
39
39
|
static getUri(filePath: string): Promise<string>;
|
|
40
40
|
/**
|
|
41
|
-
*
|
|
41
|
+
* 파일 쓰기
|
|
42
42
|
*/
|
|
43
43
|
static writeFile(filePath: string, data: string | Bytes): Promise<void>;
|
|
44
44
|
/**
|
|
45
|
-
*
|
|
45
|
+
* 파일 읽기 (기본: Bytes, encoding "utf8" 지정 시: string)
|
|
46
46
|
*/
|
|
47
47
|
static readFile(filePath: string): Promise<Bytes>;
|
|
48
48
|
static readFile(filePath: string, encoding: "utf8"): Promise<string>;
|
|
49
49
|
/**
|
|
50
|
-
*
|
|
50
|
+
* 파일/디렉토리 삭제 (재귀)
|
|
51
51
|
*/
|
|
52
52
|
static remove(targetPath: string): Promise<void>;
|
|
53
53
|
/**
|
|
54
|
-
*
|
|
54
|
+
* 디렉토리 생성 (재귀)
|
|
55
55
|
*/
|
|
56
56
|
static mkdir(targetPath: string): Promise<void>;
|
|
57
57
|
/**
|
|
58
|
-
*
|
|
58
|
+
* 존재 여부 확인
|
|
59
59
|
*/
|
|
60
60
|
static exists(targetPath: string): Promise<boolean>;
|
|
61
61
|
}
|
package/dist/FileSystem.js
CHANGED
|
@@ -1,104 +1,110 @@
|
|
|
1
1
|
import { registerPlugin } from "@capacitor/core";
|
|
2
2
|
import { bytes } from "@simplysm/core-common";
|
|
3
3
|
const fileSystemPlugin = registerPlugin("FileSystem", {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
web: async () => {
|
|
5
|
+
const { FileSystemWeb } = await import("./web/FileSystemWeb.js");
|
|
6
|
+
return new FileSystemWeb();
|
|
7
|
+
},
|
|
8
8
|
});
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
static async requestPermissions() {
|
|
23
|
-
await fileSystemPlugin.requestPermissions();
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Read directory
|
|
27
|
-
*/
|
|
28
|
-
static async readdir(dirPath) {
|
|
29
|
-
const result = await fileSystemPlugin.readdir({ path: dirPath });
|
|
30
|
-
return result.files;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Get storage path
|
|
34
|
-
* @param type Storage type
|
|
35
|
-
* - external: External storage root (Environment.getExternalStorageDirectory)
|
|
36
|
-
* - externalFiles: App-specific external files directory
|
|
37
|
-
* - externalCache: App-specific external cache directory
|
|
38
|
-
* - externalMedia: App-specific external media directory
|
|
39
|
-
* - appData: App data directory
|
|
40
|
-
* - appFiles: App files directory
|
|
41
|
-
* - appCache: App cache directory
|
|
42
|
-
*/
|
|
43
|
-
static async getStoragePath(type) {
|
|
44
|
-
const result = await fileSystemPlugin.getStoragePath({ type });
|
|
45
|
-
return result.path;
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Get file URI (FileProvider)
|
|
49
|
-
*/
|
|
50
|
-
static async getUri(filePath) {
|
|
51
|
-
const result = await fileSystemPlugin.getUri({ path: filePath });
|
|
52
|
-
return result.uri;
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Write file
|
|
56
|
-
*/
|
|
57
|
-
static async writeFile(filePath, data) {
|
|
58
|
-
if (typeof data !== "string") {
|
|
59
|
-
await fileSystemPlugin.writeFile({
|
|
60
|
-
path: filePath,
|
|
61
|
-
data: bytes.toBase64(data),
|
|
62
|
-
encoding: "base64"
|
|
63
|
-
});
|
|
64
|
-
} else {
|
|
65
|
-
await fileSystemPlugin.writeFile({
|
|
66
|
-
path: filePath,
|
|
67
|
-
data,
|
|
68
|
-
encoding: "utf8"
|
|
69
|
-
});
|
|
9
|
+
/**
|
|
10
|
+
* 파일 시스템 접근 플러그인
|
|
11
|
+
* - Android 11+: MANAGE_EXTERNAL_STORAGE 권한을 통한 전체 파일 시스템 접근
|
|
12
|
+
* - Android 10-: READ/WRITE_EXTERNAL_STORAGE 권한
|
|
13
|
+
* - Browser: IndexedDB 기반 에뮬레이션
|
|
14
|
+
*/
|
|
15
|
+
export class FileSystem {
|
|
16
|
+
/**
|
|
17
|
+
* 권한 확인
|
|
18
|
+
*/
|
|
19
|
+
static async checkPermissions() {
|
|
20
|
+
const result = await fileSystemPlugin.checkPermissions();
|
|
21
|
+
return result.granted;
|
|
70
22
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
23
|
+
/**
|
|
24
|
+
* 권한 요청
|
|
25
|
+
* - Android 11+: 설정 화면으로 이동
|
|
26
|
+
* - Android 10-: 권한 대화상자 표시
|
|
27
|
+
*/
|
|
28
|
+
static async requestPermissions() {
|
|
29
|
+
await fileSystemPlugin.requestPermissions();
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* 디렉토리 읽기
|
|
33
|
+
*/
|
|
34
|
+
static async readdir(dirPath) {
|
|
35
|
+
const result = await fileSystemPlugin.readdir({ path: dirPath });
|
|
36
|
+
return result.files;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* 저장소 경로 조회
|
|
40
|
+
* @param type 저장소 유형
|
|
41
|
+
* - external: 외부 저장소 루트 (Environment.getExternalStorageDirectory)
|
|
42
|
+
* - externalFiles: 앱 전용 외부 파일 디렉토리
|
|
43
|
+
* - externalCache: 앱 전용 외부 캐시 디렉토리
|
|
44
|
+
* - externalMedia: 앱 전용 외부 미디어 디렉토리
|
|
45
|
+
* - appData: 앱 데이터 디렉토리
|
|
46
|
+
* - appFiles: 앱 파일 디렉토리
|
|
47
|
+
* - appCache: 앱 캐시 디렉토리
|
|
48
|
+
*/
|
|
49
|
+
static async getStoragePath(type) {
|
|
50
|
+
const result = await fileSystemPlugin.getStoragePath({ type });
|
|
51
|
+
return result.path;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* 파일 URI 조회 (FileProvider)
|
|
55
|
+
*/
|
|
56
|
+
static async getUri(filePath) {
|
|
57
|
+
const result = await fileSystemPlugin.getUri({ path: filePath });
|
|
58
|
+
return result.uri;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* 파일 쓰기
|
|
62
|
+
*/
|
|
63
|
+
static async writeFile(filePath, data) {
|
|
64
|
+
if (typeof data !== "string") {
|
|
65
|
+
// Bytes (Uint8Array) - cross-realm 환경에서도 안전하게 동작
|
|
66
|
+
await fileSystemPlugin.writeFile({
|
|
67
|
+
path: filePath,
|
|
68
|
+
data: bytes.toBase64(data),
|
|
69
|
+
encoding: "base64",
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
await fileSystemPlugin.writeFile({
|
|
74
|
+
path: filePath,
|
|
75
|
+
data,
|
|
76
|
+
encoding: "utf8",
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
static async readFile(filePath, encoding) {
|
|
81
|
+
if (encoding === "utf8") {
|
|
82
|
+
const result = await fileSystemPlugin.readFile({ path: filePath, encoding: "utf8" });
|
|
83
|
+
return result.data;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
const result = await fileSystemPlugin.readFile({ path: filePath, encoding: "base64" });
|
|
87
|
+
return bytes.fromBase64(result.data);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* 파일/디렉토리 삭제 (재귀)
|
|
92
|
+
*/
|
|
93
|
+
static async remove(targetPath) {
|
|
94
|
+
await fileSystemPlugin.remove({ path: targetPath });
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* 디렉토리 생성 (재귀)
|
|
98
|
+
*/
|
|
99
|
+
static async mkdir(targetPath) {
|
|
100
|
+
await fileSystemPlugin.mkdir({ path: targetPath });
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* 존재 여부 확인
|
|
104
|
+
*/
|
|
105
|
+
static async exists(targetPath) {
|
|
106
|
+
const result = await fileSystemPlugin.exists({ path: targetPath });
|
|
107
|
+
return result.exists;
|
|
79
108
|
}
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Delete file/directory (recursive)
|
|
83
|
-
*/
|
|
84
|
-
static async remove(targetPath) {
|
|
85
|
-
await fileSystemPlugin.remove({ path: targetPath });
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Create directory (recursive)
|
|
89
|
-
*/
|
|
90
|
-
static async mkdir(targetPath) {
|
|
91
|
-
await fileSystemPlugin.mkdir({ path: targetPath });
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Check existence
|
|
95
|
-
*/
|
|
96
|
-
static async exists(targetPath) {
|
|
97
|
-
const result = await fileSystemPlugin.exists({ path: targetPath });
|
|
98
|
-
return result.exists;
|
|
99
|
-
}
|
|
100
109
|
}
|
|
101
|
-
|
|
102
|
-
FileSystem
|
|
103
|
-
};
|
|
104
|
-
//# sourceMappingURL=FileSystem.js.map
|
|
110
|
+
//# sourceMappingURL=FileSystem.js.map
|
package/dist/FileSystem.js.map
CHANGED
|
@@ -1,6 +1 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/FileSystem.ts"],
|
|
4
|
-
"mappings": "AAAA,SAAS,sBAAsB;AAG/B,SAAS,aAAa;AAEtB,MAAM,mBAAmB,eAAiC,cAAc;AAAA,EACtE,KAAK,YAAY;AACf,UAAM,EAAE,cAAc,IAAI,MAAM,OAAO,qBAAqB;AAC5D,WAAO,IAAI,cAAc;AAAA,EAC3B;AACF,CAAC;AAQM,MAAe,WAAW;AAAA;AAAA;AAAA;AAAA,EAI/B,aAAa,mBAAqC;AAChD,UAAM,SAAS,MAAM,iBAAiB,iBAAiB;AACvD,WAAO,OAAO;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAa,qBAAoC;AAC/C,UAAM,iBAAiB,mBAAmB;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,QAAQ,SAAsC;AACzD,UAAM,SAAS,MAAM,iBAAiB,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAC/D,WAAO,OAAO;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,aAAa,eAAe,MAAoC;AAC9D,UAAM,SAAS,MAAM,iBAAiB,eAAe,EAAE,KAAK,CAAC;AAC7D,WAAO,OAAO;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,OAAO,UAAmC;AACrD,UAAM,SAAS,MAAM,iBAAiB,OAAO,EAAE,MAAM,SAAS,CAAC;AAC/D,WAAO,OAAO;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,UAAU,UAAkB,MAAqC;AAC5E,QAAI,OAAO,SAAS,UAAU;AAE5B,YAAM,iBAAiB,UAAU;AAAA,QAC/B,MAAM;AAAA,QACN,MAAM,MAAM,SAAS,IAAI;AAAA,QACzB,UAAU;AAAA,MACZ,CAAC;AAAA,IACH,OAAO;AACL,YAAM,iBAAiB,UAAU;AAAA,QAC/B,MAAM;AAAA,QACN;AAAA,QACA,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAOA,aAAa,SAAS,UAAkB,UAA4C;AAClF,QAAI,aAAa,QAAQ;AACvB,YAAM,SAAS,MAAM,iBAAiB,SAAS,EAAE,MAAM,UAAU,UAAU,OAAO,CAAC;AACnF,aAAO,OAAO;AAAA,IAChB,OAAO;AACL,YAAM,SAAS,MAAM,iBAAiB,SAAS,EAAE,MAAM,UAAU,UAAU,SAAS,CAAC;AACrF,aAAO,MAAM,WAAW,OAAO,IAAI;AAAA,IACrC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,OAAO,YAAmC;AACrD,UAAM,iBAAiB,OAAO,EAAE,MAAM,WAAW,CAAC;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,MAAM,YAAmC;AACpD,UAAM,iBAAiB,MAAM,EAAE,MAAM,WAAW,CAAC;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,OAAO,YAAsC;AACxD,UAAM,SAAS,MAAM,iBAAiB,OAAO,EAAE,MAAM,WAAW,CAAC;AACjE,WAAO,OAAO;AAAA,EAChB;AACF;",
|
|
5
|
-
"names": []
|
|
6
|
-
}
|
|
1
|
+
{"version":3,"file":"FileSystem.js","sourceRoot":"","sources":["..\\src\\FileSystem.ts"],"names":[],"mappings":"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"}
|
package/dist/FileSystemPlugin.js
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
export {};
|
|
2
|
+
//# sourceMappingURL=FileSystemPlugin.js.map
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -19,9 +19,9 @@ export declare class FileSystemWeb extends WebPlugin implements FileSystemPlugin
|
|
|
19
19
|
path: string;
|
|
20
20
|
}>;
|
|
21
21
|
/**
|
|
22
|
-
*
|
|
23
|
-
* @warning
|
|
24
|
-
*
|
|
22
|
+
* 파일의 Blob URL을 반환합니다.
|
|
23
|
+
* @warning 반환된 URI는 사용 후 `URL.revokeObjectURL(uri)`를 호출하여 해제해야 합니다.
|
|
24
|
+
* 해제하지 않으면 메모리 누수가 발생할 수 있습니다.
|
|
25
25
|
*/
|
|
26
26
|
getUri(options: {
|
|
27
27
|
path: string;
|