@simplysm/capacitor-plugin-file-system 14.0.46 → 14.0.48
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/README.md +133 -0
- package/docs/file-operations.md +154 -0
- package/docs/permissions.md +84 -0
- package/docs/storage-paths.md +107 -0
- package/docs/types.md +83 -0
- package/package.json +6 -5
package/README.md
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# @simplysm/capacitor-plugin-file-system
|
|
2
|
+
|
|
3
|
+
Capacitor 플러그인으로 Android 파일 시스템 접근을 제공합니다. 외부 저장소 전체 접근 및 앱 전용 디렉토리 접근을 지원하며, 브라우저 환경에서는 IndexedDB 기반 가상 파일 시스템으로 에뮬레이션합니다.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @simplysm/capacitor-plugin-file-system
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## API Overview
|
|
12
|
+
|
|
13
|
+
### Core File System Operations
|
|
14
|
+
|
|
15
|
+
| API | Type | Description |
|
|
16
|
+
|-----|------|-------------|
|
|
17
|
+
| `FileSystem.readdir` | function | 디렉토리의 파일/폴더 목록 조회 |
|
|
18
|
+
| `FileSystem.writeFile` | function | 파일 쓰기 (문자열 또는 Bytes) |
|
|
19
|
+
| `FileSystem.readFile` | function | 파일 읽기 (기본: Bytes, encoding="utf8" 시: string) |
|
|
20
|
+
| `FileSystem.remove` | function | 파일/디렉토리 삭제 (재귀) |
|
|
21
|
+
| `FileSystem.mkdir` | function | 디렉토리 생성 (재귀) |
|
|
22
|
+
| `FileSystem.exists` | function | 파일/디렉토리 존재 여부 확인 |
|
|
23
|
+
|
|
24
|
+
→ See [docs/file-operations.md](./docs/file-operations.md) for details.
|
|
25
|
+
|
|
26
|
+
### Storage & Paths
|
|
27
|
+
|
|
28
|
+
| API | Type | Description |
|
|
29
|
+
|-----|------|-------------|
|
|
30
|
+
| `FileSystem.getStoragePath` | function | 저장소 유형별 경로 조회 (external, externalFiles, appCache 등) |
|
|
31
|
+
| `FileSystem.getUri` | function | 파일 URI 조회 (FileProvider Blob URL) |
|
|
32
|
+
| `StorageType` | type | 저장소 유형 (external, externalFiles, externalCache, externalMedia, appData, appFiles, appCache) |
|
|
33
|
+
|
|
34
|
+
→ See [docs/storage-paths.md](./docs/storage-paths.md) for details.
|
|
35
|
+
|
|
36
|
+
### Permissions
|
|
37
|
+
|
|
38
|
+
| API | Type | Description |
|
|
39
|
+
|-----|------|-------------|
|
|
40
|
+
| `FileSystem.checkPermissions` | function | 파일 시스템 접근 권한 확인 |
|
|
41
|
+
| `FileSystem.requestPermissions` | function | 파일 시스템 접근 권한 요청 |
|
|
42
|
+
|
|
43
|
+
→ See [docs/permissions.md](./docs/permissions.md) for details.
|
|
44
|
+
|
|
45
|
+
### Types
|
|
46
|
+
|
|
47
|
+
| API | Type | Description |
|
|
48
|
+
|-----|------|-------------|
|
|
49
|
+
| `FileInfo` | interface | 파일/디렉토리 정보 (name, isDirectory) |
|
|
50
|
+
|
|
51
|
+
→ See [docs/types.md](./docs/types.md) for details.
|
|
52
|
+
|
|
53
|
+
## Usage Examples
|
|
54
|
+
|
|
55
|
+
### 권한 확인 후 파일 읽기
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
import { FileSystem } from "@simplysm/capacitor-plugin-file-system";
|
|
59
|
+
|
|
60
|
+
async function readAppFile() {
|
|
61
|
+
// 권한 확인
|
|
62
|
+
const hasPermission = await FileSystem.checkPermissions();
|
|
63
|
+
if (!hasPermission) {
|
|
64
|
+
await FileSystem.requestPermissions();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// 앱 파일 디렉토리 경로 조회
|
|
68
|
+
const appFilesPath = await FileSystem.getStoragePath("appFiles");
|
|
69
|
+
|
|
70
|
+
// 파일 읽기 (문자열)
|
|
71
|
+
const content = await FileSystem.readFile(appFilesPath + "/config.json", "utf8");
|
|
72
|
+
console.log(content);
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Bytes 데이터 쓰기
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
import { FileSystem } from "@simplysm/capacitor-plugin-file-system";
|
|
80
|
+
import { bytes } from "@simplysm/core-common";
|
|
81
|
+
|
|
82
|
+
async function writeAppDataAsBytes() {
|
|
83
|
+
const appCachePath = await FileSystem.getStoragePath("appCache");
|
|
84
|
+
|
|
85
|
+
// Uint8Array로 작성
|
|
86
|
+
const data = new Uint8Array([0x89, 0x50, 0x4e, 0x47]); // PNG header
|
|
87
|
+
await FileSystem.writeFile(appCachePath + "/image.png", data);
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### 디렉토리 탐색
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
import { FileSystem } from "@simplysm/capacitor-plugin-file-system";
|
|
95
|
+
|
|
96
|
+
async function listDirectory(dirPath: string) {
|
|
97
|
+
const files = await FileSystem.readdir(dirPath);
|
|
98
|
+
|
|
99
|
+
for (const file of files) {
|
|
100
|
+
console.log(`${file.name} ${file.isDirectory ? "(dir)" : "(file)"}`);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// 삭제 전 존재 여부 확인
|
|
104
|
+
const exists = await FileSystem.exists(dirPath);
|
|
105
|
+
if (exists) {
|
|
106
|
+
await FileSystem.remove(dirPath);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### 브라우저에서 Blob URL 사용
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
import { FileSystem } from "@simplysm/capacitor-plugin-file-system";
|
|
115
|
+
|
|
116
|
+
async function showImageInBrowser() {
|
|
117
|
+
const appFilesPath = await FileSystem.getStoragePath("appFiles");
|
|
118
|
+
const imagePath = appFilesPath + "/photo.jpg";
|
|
119
|
+
|
|
120
|
+
// Blob URL 획득
|
|
121
|
+
const uri = await FileSystem.getUri(imagePath);
|
|
122
|
+
|
|
123
|
+
// DOM에서 사용
|
|
124
|
+
const img = document.createElement("img");
|
|
125
|
+
img.src = uri;
|
|
126
|
+
document.body.appendChild(img);
|
|
127
|
+
|
|
128
|
+
// 사용 완료 후 URL 해제 (메모리 누수 방지)
|
|
129
|
+
img.onload = () => {
|
|
130
|
+
URL.revokeObjectURL(uri);
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
```
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# File Operations
|
|
2
|
+
|
|
3
|
+
## `FileSystem.readdir`
|
|
4
|
+
|
|
5
|
+
디렉토리의 파일과 폴더 목록을 조회합니다.
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
static async readdir(dirPath: string): Promise<FileInfo[]>
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
| Parameter | Type | Description |
|
|
12
|
+
|-----------|------|-------------|
|
|
13
|
+
| `dirPath` | string | 조회할 디렉토리의 절대 경로 |
|
|
14
|
+
|
|
15
|
+
**Return**: 디렉토리 내 파일/폴더 목록 (각 항목은 name과 isDirectory 포함)
|
|
16
|
+
|
|
17
|
+
**Throws**: 디렉토리가 존재하지 않거나 허용되지 않는 경로일 경우 Error
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
const files = await FileSystem.readdir("/storage/emulated/0/Documents");
|
|
21
|
+
for (const file of files) {
|
|
22
|
+
console.log(`${file.name} ${file.isDirectory ? "[DIR]" : ""}`);
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## `FileSystem.writeFile`
|
|
27
|
+
|
|
28
|
+
파일을 작성합니다. 문자열 또는 Bytes(Uint8Array) 데이터를 지원합니다.
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
static async writeFile(filePath: string, data: string | Bytes): Promise<void>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
| Parameter | Type | Description |
|
|
35
|
+
|-----------|------|-------------|
|
|
36
|
+
| `filePath` | string | 쓸 파일의 절대 경로 |
|
|
37
|
+
| `data` | string \| Bytes | 파일 내용 (문자열 또는 Uint8Array) |
|
|
38
|
+
|
|
39
|
+
**Behavior**:
|
|
40
|
+
- 문자열인 경우: UTF-8 인코딩으로 저장 (encoding: "utf8")
|
|
41
|
+
- Bytes인 경우: Base64 인코딩으로 저장 (encoding: "base64")
|
|
42
|
+
- 상위 디렉토리가 없으면 자동 생성 (웹 환경에서만)
|
|
43
|
+
|
|
44
|
+
**Throws**: 쓰기 권한 없을 경우 Error
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
// 문자열 쓰기
|
|
48
|
+
await FileSystem.writeFile("/storage/emulated/0/Documents/notes.txt", "Hello, World!");
|
|
49
|
+
|
|
50
|
+
// Bytes 쓰기 (예: PNG 이미지)
|
|
51
|
+
const pngData = new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
|
|
52
|
+
await FileSystem.writeFile("/storage/emulated/0/Pictures/image.png", pngData);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## `FileSystem.readFile`
|
|
56
|
+
|
|
57
|
+
파일을 읽습니다. 기본적으로 Bytes를 반환하며, encoding 파라미터로 문자열 반환을 지정할 수 있습니다.
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
static async readFile(filePath: string): Promise<Bytes>;
|
|
61
|
+
static async readFile(filePath: string, encoding: "utf8"): Promise<string>;
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
| Parameter | Type | Description |
|
|
65
|
+
|-----------|------|-------------|
|
|
66
|
+
| `filePath` | string | 읽을 파일의 절대 경로 |
|
|
67
|
+
| `encoding` | "utf8" (optional) | "utf8"일 경우 string 반환, 생략 시 Bytes 반환 |
|
|
68
|
+
|
|
69
|
+
**Return**:
|
|
70
|
+
- encoding 생략: `Promise<Bytes>` (Uint8Array)
|
|
71
|
+
- encoding="utf8": `Promise<string>`
|
|
72
|
+
|
|
73
|
+
**Throws**: 파일이 없거나 읽기 권한이 없을 경우 Error
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
// Bytes로 읽기 (기본)
|
|
77
|
+
const imageData = await FileSystem.readFile("/storage/emulated/0/Pictures/photo.jpg");
|
|
78
|
+
console.log(imageData instanceof Uint8Array); // true
|
|
79
|
+
|
|
80
|
+
// 문자열로 읽기
|
|
81
|
+
const config = await FileSystem.readFile("/storage/emulated/0/Documents/config.json", "utf8");
|
|
82
|
+
const obj = JSON.parse(config);
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## `FileSystem.remove`
|
|
86
|
+
|
|
87
|
+
파일 또는 디렉토리를 삭제합니다. 디렉토리인 경우 재귀적으로 삭제됩니다.
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
static async remove(targetPath: string): Promise<void>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
| Parameter | Type | Description |
|
|
94
|
+
|-----------|------|-------------|
|
|
95
|
+
| `targetPath` | string | 삭제할 파일/디렉토리의 절대 경로 |
|
|
96
|
+
|
|
97
|
+
**Behavior**:
|
|
98
|
+
- 파일: 즉시 삭제
|
|
99
|
+
- 디렉토리: 하위의 모든 파일/폴더 포함하여 재귀 삭제
|
|
100
|
+
- 웹 환경: 경로 프리픽스로 모든 관련 항목 삭제
|
|
101
|
+
|
|
102
|
+
**Throws**: 대상이 존재하지 않거나 권한 없을 경우 Error
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
// 파일 삭제
|
|
106
|
+
await FileSystem.remove("/storage/emulated/0/Documents/temp.txt");
|
|
107
|
+
|
|
108
|
+
// 디렉토리 재귀 삭제
|
|
109
|
+
await FileSystem.remove("/storage/emulated/0/Documents/old_backup");
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## `FileSystem.mkdir`
|
|
113
|
+
|
|
114
|
+
디렉토리를 생성합니다. 상위 경로가 없는 경우 자동으로 생성됩니다 (재귀 생성).
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
static async mkdir(targetPath: string): Promise<void>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
| Parameter | Type | Description |
|
|
121
|
+
|-----------|------|-------------|
|
|
122
|
+
| `targetPath` | string | 생성할 디렉토리의 절대 경로 |
|
|
123
|
+
|
|
124
|
+
**Behavior**:
|
|
125
|
+
- 중간 경로가 없어도 자동 생성
|
|
126
|
+
- 이미 존재하면 아무 동작 없음
|
|
127
|
+
|
|
128
|
+
**Throws**: 권한 없을 경우 Error
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
// 중간 경로 자동 생성
|
|
132
|
+
await FileSystem.mkdir("/storage/emulated/0/Documents/projects/2025/Q1");
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## `FileSystem.exists`
|
|
136
|
+
|
|
137
|
+
파일 또는 디렉토리의 존재 여부를 확인합니다.
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
static async exists(targetPath: string): Promise<boolean>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
| Parameter | Type | Description |
|
|
144
|
+
|-----------|------|-------------|
|
|
145
|
+
| `targetPath` | string | 확인할 파일/디렉토리의 절대 경로 |
|
|
146
|
+
|
|
147
|
+
**Return**: true (존재), false (존재하지 않음)
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
const exists = await FileSystem.exists("/storage/emulated/0/Documents/config.json");
|
|
151
|
+
if (!exists) {
|
|
152
|
+
await FileSystem.writeFile("/storage/emulated/0/Documents/config.json", "{}");
|
|
153
|
+
}
|
|
154
|
+
```
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Permissions
|
|
2
|
+
|
|
3
|
+
## `FileSystem.checkPermissions`
|
|
4
|
+
|
|
5
|
+
파일 시스템 접근 권한 여부를 확인합니다.
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
static async checkPermissions(): Promise<boolean>
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
**Return**: true (권한 허용), false (권한 거부)
|
|
12
|
+
|
|
13
|
+
**플랫폼별 동작**:
|
|
14
|
+
- **Android**: 현재 권한 상태 확인 (MANAGE_EXTERNAL_STORAGE 또는 READ/WRITE_EXTERNAL_STORAGE)
|
|
15
|
+
- **Web**: 항상 true (권한 개념 없음)
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
const hasPermission = await FileSystem.checkPermissions();
|
|
19
|
+
if (hasPermission) {
|
|
20
|
+
// 파일 접근 가능
|
|
21
|
+
const files = await FileSystem.readdir("/storage/emulated/0/Documents");
|
|
22
|
+
} else {
|
|
23
|
+
// 권한 요청 필요
|
|
24
|
+
await FileSystem.requestPermissions();
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## `FileSystem.requestPermissions`
|
|
29
|
+
|
|
30
|
+
파일 시스템 접근 권한을 요청합니다.
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
static async requestPermissions(): Promise<void>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**플랫폼별 동작**:
|
|
37
|
+
- **Android 11+ (API 30+)**:
|
|
38
|
+
- `MANAGE_EXTERNAL_STORAGE` 권한 요청
|
|
39
|
+
- 설정 화면으로 이동하여 사용자가 수동으로 허용
|
|
40
|
+
- 권한 대화상자가 표시되지 않음
|
|
41
|
+
- **Android 10 이하 (API 29-)**:
|
|
42
|
+
- `READ_EXTERNAL_STORAGE` + `WRITE_EXTERNAL_STORAGE` 요청
|
|
43
|
+
- 표준 권한 대화상자 표시
|
|
44
|
+
- **Web**: 아무 동작 없음
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
async function ensureFileSystemAccess() {
|
|
48
|
+
const hasPermission = await FileSystem.checkPermissions();
|
|
49
|
+
|
|
50
|
+
if (!hasPermission) {
|
|
51
|
+
try {
|
|
52
|
+
await FileSystem.requestPermissions();
|
|
53
|
+
console.log("Permission granted");
|
|
54
|
+
} catch (error) {
|
|
55
|
+
console.error("Permission request failed:", error);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// 앱 시작 시 권한 확인
|
|
61
|
+
await ensureFileSystemAccess();
|
|
62
|
+
|
|
63
|
+
// 외부 저장소 접근
|
|
64
|
+
const externalPath = await FileSystem.getStoragePath("external");
|
|
65
|
+
const files = await FileSystem.readdir(externalPath);
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## 권한 관련 주의사항
|
|
69
|
+
|
|
70
|
+
### Android 11+ (Scoped Storage)
|
|
71
|
+
|
|
72
|
+
- `MANAGE_EXTERNAL_STORAGE` 권한은 특수 권한이며, 일반 권한 대화상자로 요청할 수 없습니다.
|
|
73
|
+
- 권한 요청 시 설정 앱으로 이동하므로 사용자가 직접 허용/거부를 선택해야 합니다.
|
|
74
|
+
- AndroidManifest.xml에 `android.permission.MANAGE_EXTERNAL_STORAGE`를 선언해야 합니다.
|
|
75
|
+
|
|
76
|
+
### Android 10 이하
|
|
77
|
+
|
|
78
|
+
- `READ_EXTERNAL_STORAGE`, `WRITE_EXTERNAL_STORAGE` 권한이 필요합니다.
|
|
79
|
+
- 이 권한들은 위험한(Dangerous) 권한으로 분류되어 런타임 권한 요청이 필요합니다.
|
|
80
|
+
|
|
81
|
+
### 웹 환경
|
|
82
|
+
|
|
83
|
+
- 권한 개념이 없으며, IndexedDB 기반 가상 파일 시스템을 사용합니다.
|
|
84
|
+
- 사용자는 브라우저 저장소 한도에만 제한됩니다.
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Storage & Paths
|
|
2
|
+
|
|
3
|
+
## `FileSystem.getStoragePath`
|
|
4
|
+
|
|
5
|
+
저장소 유형별로 기기의 실제 경로(Android) 또는 가상 경로(웹)를 반환합니다.
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
static async getStoragePath(type: StorageType): Promise<string>
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
| Parameter | Type | Description |
|
|
12
|
+
|-----------|------|-------------|
|
|
13
|
+
| `type` | StorageType | 저장소 유형 |
|
|
14
|
+
|
|
15
|
+
**Return**: 절대 경로 문자열
|
|
16
|
+
|
|
17
|
+
**StorageType 종류**:
|
|
18
|
+
|
|
19
|
+
| Type | Android Path | Web Path | 설명 |
|
|
20
|
+
|------|--------------|----------|------|
|
|
21
|
+
| `external` | `Environment.getExternalStorageDirectory()` | `/webfs/external` | 외부 저장소 루트 (공유 저장소) |
|
|
22
|
+
| `externalFiles` | `getExternalFilesDir(null)` | `/webfs/externalFiles` | 앱 전용 외부 파일 디렉토리 |
|
|
23
|
+
| `externalCache` | `externalCacheDir` | `/webfs/externalCache` | 앱 전용 외부 캐시 디렉토리 |
|
|
24
|
+
| `externalMedia` | `externalMediaDirs[0]` | `/webfs/externalMedia` | 앱 전용 외부 미디어 디렉토리 |
|
|
25
|
+
| `appData` | `applicationInfo.dataDir` | `/webfs/appData` | 앱 데이터 디렉토리 (내부) |
|
|
26
|
+
| `appFiles` | `filesDir` | `/webfs/appFiles` | 앱 파일 디렉토리 (내부) |
|
|
27
|
+
| `appCache` | `cacheDir` | `/webfs/appCache` | 앱 캐시 디렉토리 (내부) |
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
// 앱 캐시 디렉토리에 임시 파일 작성
|
|
31
|
+
const cachePath = await FileSystem.getStoragePath("appCache");
|
|
32
|
+
await FileSystem.writeFile(cachePath + "/temp.dat", "temporary data");
|
|
33
|
+
|
|
34
|
+
// 외부 파일 디렉토리에 문서 저장
|
|
35
|
+
const filesPath = await FileSystem.getStoragePath("externalFiles");
|
|
36
|
+
await FileSystem.mkdir(filesPath + "/documents");
|
|
37
|
+
await FileSystem.writeFile(filesPath + "/documents/report.pdf", pdfBytes);
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## `FileSystem.getUri`
|
|
41
|
+
|
|
42
|
+
파일의 URI를 조회합니다. 주로 Blob URL(웹) 또는 FileProvider URI(Android)로 반환됩니다.
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
static async getUri(filePath: string): Promise<string>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
| Parameter | Type | Description |
|
|
49
|
+
|-----------|------|-------------|
|
|
50
|
+
| `filePath` | string | 파일의 절대 경로 |
|
|
51
|
+
|
|
52
|
+
**Return**: URI 문자열
|
|
53
|
+
- Android: `content://` scheme의 FileProvider URI
|
|
54
|
+
- Web: `blob://` scheme의 Blob URL
|
|
55
|
+
|
|
56
|
+
**Web 환경 주의사항**:
|
|
57
|
+
반환된 Blob URL은 사용 후 반드시 `URL.revokeObjectURL(uri)`로 해제해야 합니다. 해제하지 않으면 메모리 누수가 발생할 수 있습니다.
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
// 웹 환경: Blob URL 사용 후 해제
|
|
61
|
+
const imagePath = await FileSystem.getStoragePath("appFiles");
|
|
62
|
+
const imageFile = imagePath + "/photo.jpg";
|
|
63
|
+
|
|
64
|
+
const uri = await FileSystem.getUri(imageFile);
|
|
65
|
+
|
|
66
|
+
const img = document.createElement("img");
|
|
67
|
+
img.src = uri;
|
|
68
|
+
img.onload = () => {
|
|
69
|
+
URL.revokeObjectURL(uri); // 메모리 해제
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// Android 환경: FileProvider URI를 다른 앱과 공유
|
|
73
|
+
const documentPath = await FileSystem.getStoragePath("externalFiles");
|
|
74
|
+
const documentFile = documentPath + "/report.pdf";
|
|
75
|
+
const contentUri = await FileSystem.getUri(documentFile);
|
|
76
|
+
|
|
77
|
+
// contentUri를 Intent의 data로 사용하여 다른 앱 실행
|
|
78
|
+
const intent = new Intent(Intent.ACTION_VIEW);
|
|
79
|
+
intent.setDataAndType(Uri.parse(contentUri), "application/pdf");
|
|
80
|
+
startActivity(intent);
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## `StorageType`
|
|
84
|
+
|
|
85
|
+
저장소 유형을 나타내는 union type입니다.
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
type StorageType =
|
|
89
|
+
| "external"
|
|
90
|
+
| "externalFiles"
|
|
91
|
+
| "externalCache"
|
|
92
|
+
| "externalMedia"
|
|
93
|
+
| "appData"
|
|
94
|
+
| "appFiles"
|
|
95
|
+
| "appCache";
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**사용 가이드**:
|
|
99
|
+
- **내부 저장소 (앱 전용)**:
|
|
100
|
+
- `appData`: 앱 상태 데이터 (자동 백업 대상)
|
|
101
|
+
- `appFiles`: 일반 파일 저장
|
|
102
|
+
- `appCache`: 임시 캐시 (시스템이 필요 시 삭제 가능)
|
|
103
|
+
- **외부 저장소 (공유 또는 앱 전용)**:
|
|
104
|
+
- `external`: 전체 외부 저장소 (권한 필요)
|
|
105
|
+
- `externalFiles`: 앱 전용 외부 파일 (권한 필요)
|
|
106
|
+
- `externalCache`: 앱 전용 외부 캐시 (권한 필요)
|
|
107
|
+
- `externalMedia`: 앱 전용 외부 미디어 (권한 필요)
|
package/docs/types.md
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Types
|
|
2
|
+
|
|
3
|
+
## `FileInfo`
|
|
4
|
+
|
|
5
|
+
파일 또는 디렉토리의 정보를 나타내는 인터페이스입니다.
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
interface FileInfo {
|
|
9
|
+
name: string;
|
|
10
|
+
isDirectory: boolean;
|
|
11
|
+
}
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
| Field | Type | Description |
|
|
15
|
+
|-------|------|-------------|
|
|
16
|
+
| `name` | string | 파일 또는 디렉토리의 이름 (경로 제외, 확장자 포함) |
|
|
17
|
+
| `isDirectory` | boolean | true일 경우 디렉토리, false일 경우 파일 |
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
// 디렉토리 읽기 결과
|
|
21
|
+
const files = await FileSystem.readdir("/storage/emulated/0/Documents");
|
|
22
|
+
|
|
23
|
+
// FileInfo 배열 처리
|
|
24
|
+
for (const file of files) {
|
|
25
|
+
if (file.isDirectory) {
|
|
26
|
+
console.log(`📁 ${file.name} (directory)`);
|
|
27
|
+
} else {
|
|
28
|
+
console.log(`📄 ${file.name} (file)`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## `FileSystemPlugin`
|
|
34
|
+
|
|
35
|
+
Capacitor 플러그인 인터페이스입니다. 일반적으로 `FileSystem` 파사드를 통해 간접적으로 사용됩니다.
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
interface FileSystemPlugin {
|
|
39
|
+
checkPermissions(): Promise<{ granted: boolean }>;
|
|
40
|
+
requestPermissions(): Promise<void>;
|
|
41
|
+
readdir(options: { path: string }): Promise<{ files: FileInfo[] }>;
|
|
42
|
+
getStoragePath(options: { type: StorageType }): Promise<{ path: string }>;
|
|
43
|
+
getUri(options: { path: string }): Promise<{ uri: string }>;
|
|
44
|
+
writeFile(options: { path: string; data: string; encoding?: "utf8" | "base64" }): Promise<void>;
|
|
45
|
+
readFile(options: { path: string; encoding?: "utf8" | "base64" }): Promise<{ data: string }>;
|
|
46
|
+
remove(options: { path: string }): Promise<void>;
|
|
47
|
+
mkdir(options: { path: string }): Promise<void>;
|
|
48
|
+
exists(options: { path: string }): Promise<{ exists: boolean }>;
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**참고**: 이 인터페이스는 내부 플러그인 구현용이며, 외부 사용자는 `FileSystem` 파사드의 정적 메서드를 사용합니다.
|
|
53
|
+
|
|
54
|
+
## `Bytes`
|
|
55
|
+
|
|
56
|
+
이 패키지에서는 `@simplysm/core-common`의 `Bytes` 타입(Uint8Array의 별칭)을 사용합니다.
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
import type { Bytes } from "@simplysm/core-common";
|
|
60
|
+
import { bytes } from "@simplysm/core-common";
|
|
61
|
+
|
|
62
|
+
// Bytes = Uint8Array
|
|
63
|
+
const data: Bytes = new Uint8Array([0x89, 0x50, 0x4e, 0x47]);
|
|
64
|
+
|
|
65
|
+
// Base64 변환 유틸리티
|
|
66
|
+
const base64Str = bytes.toBase64(data); // Bytes → Base64 문자열
|
|
67
|
+
const bytesData = bytes.fromBase64(base64Str); // Base64 문자열 → Bytes
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## `StorageType`
|
|
71
|
+
|
|
72
|
+
저장소 유형 union type입니다. 자세한 설명은 [storage-paths.md](./storage-paths.md)를 참조하세요.
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
type StorageType =
|
|
76
|
+
| "external"
|
|
77
|
+
| "externalFiles"
|
|
78
|
+
| "externalCache"
|
|
79
|
+
| "externalMedia"
|
|
80
|
+
| "appData"
|
|
81
|
+
| "appFiles"
|
|
82
|
+
| "appCache";
|
|
83
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simplysm/capacitor-plugin-file-system",
|
|
3
|
-
"version": "14.0.
|
|
3
|
+
"version": "14.0.48",
|
|
4
4
|
"description": "심플리즘 패키지 - Capacitor 파일 시스템 플러그인",
|
|
5
5
|
"author": "simplysm",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -15,14 +15,15 @@
|
|
|
15
15
|
"files": [
|
|
16
16
|
"dist",
|
|
17
17
|
"src",
|
|
18
|
-
"android"
|
|
18
|
+
"android",
|
|
19
|
+
"docs"
|
|
19
20
|
],
|
|
20
21
|
"dependencies": {
|
|
21
|
-
"@simplysm/core-browser": "14.0.
|
|
22
|
-
"@simplysm/core-common": "14.0.
|
|
22
|
+
"@simplysm/core-browser": "14.0.48",
|
|
23
|
+
"@simplysm/core-common": "14.0.48"
|
|
23
24
|
},
|
|
24
25
|
"devDependencies": {
|
|
25
|
-
"@capacitor/core": "^7.6.
|
|
26
|
+
"@capacitor/core": "^7.6.2"
|
|
26
27
|
},
|
|
27
28
|
"peerDependencies": {
|
|
28
29
|
"@capacitor/core": "^7"
|