react-native-kookit 0.3.5 → 0.3.7
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 +22 -1
- package/TTS_CHECKLIST.md +256 -0
- package/android/src/main/java/expo/modules/kookit/ReactNativeKookitModule.kt +284 -0
- package/build/ReactNativeKookit.types.d.ts +11 -0
- package/build/ReactNativeKookit.types.d.ts.map +1 -1
- package/build/ReactNativeKookit.types.js.map +1 -1
- package/build/ReactNativeKookitModule.d.ts +37 -1
- package/build/ReactNativeKookitModule.d.ts.map +1 -1
- package/build/ReactNativeKookitModule.js.map +1 -1
- package/ios/ReactNativeKookitModule.swift +143 -0
- package/package.json +1 -1
- package/ANDROID_BUILD_FIX.md +0 -117
- package/ANDROID_FTP_UPDATE.md +0 -161
- package/ANDROID_SETUP.md +0 -188
- package/ANDROID_SMB_LIBRARY_COMPARISON.md +0 -170
- package/ANDROID_SMB_LISTSHARES_FIX.md +0 -100
- package/API_UNIFICATION.md +0 -180
- package/EXPO_PLUGIN_README.md +0 -136
- package/FTP_CLIENT_API.md +0 -301
- package/FTP_FILE_LIST_ENHANCEMENT.md +0 -186
- package/FTP_FILE_OPERATIONS.md +0 -0
- package/FTP_README.md +0 -322
- package/README_NEW.md +0 -143
- package/RELEASE_CHECKLIST.md +0 -115
- package/SMB_CLIENT_STATIC_METHODS.md +0 -175
- package/SMB_COMPLETE_GUIDE.md +0 -308
- package/SMB_HYBRID_IMPLEMENTATION.md +0 -160
- package/SMB_IMPLEMENTATION_SUMMARY.md +0 -229
- package/SMB_USAGE.md +0 -275
- package/TROUBLESHOOTING.md +0 -132
- /package/{ANDROID_PARAMETER_FIX.md → CHANGELOG_CONTENT_URI.md} +0 -0
- /package/{FTP_EXAMPLE_IMPLEMENTATION.md → IMPLEMENTATION_SUMMARY.md} +0 -0
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
# SMB Client 静态方法使用示例
|
|
2
|
-
|
|
3
|
-
SmbClient新增了多个静态方法来管理多个客户端实例:
|
|
4
|
-
|
|
5
|
-
## 新增的静态方法
|
|
6
|
-
|
|
7
|
-
### 1. `SmbClient.disposeClient(clientId: string)`
|
|
8
|
-
|
|
9
|
-
销毁指定客户端ID的客户端实例
|
|
10
|
-
|
|
11
|
-
```typescript
|
|
12
|
-
// 销毁特定的客户端
|
|
13
|
-
const disposed = await SmbClient.disposeClient("my_client_id");
|
|
14
|
-
console.log("Client disposed:", disposed); // true/false
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
### 2. `SmbClient.getClientStatus(clientId: string)`
|
|
18
|
-
|
|
19
|
-
获取指定客户端ID的状态信息
|
|
20
|
-
|
|
21
|
-
```typescript
|
|
22
|
-
// 获取客户端状态
|
|
23
|
-
const status = SmbClient.getClientStatus("my_client_id");
|
|
24
|
-
console.log("Client status:", status);
|
|
25
|
-
// 返回: {
|
|
26
|
-
// exists: true,
|
|
27
|
-
// isConnected: true,
|
|
28
|
-
// currentShare: 'C$',
|
|
29
|
-
// isDisposed: false
|
|
30
|
-
// }
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
### 3. `SmbClient.getAllClientsStatus()`
|
|
34
|
-
|
|
35
|
-
获取所有活跃客户端的状态
|
|
36
|
-
|
|
37
|
-
```typescript
|
|
38
|
-
// 获取所有客户端状态
|
|
39
|
-
const allStatus = SmbClient.getAllClientsStatus();
|
|
40
|
-
allStatus.forEach((status, clientId) => {
|
|
41
|
-
console.log(`Client ${clientId}:`, status);
|
|
42
|
-
});
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
### 4. `SmbClient.getInstance(clientId: string)`
|
|
46
|
-
|
|
47
|
-
获取指定客户端ID的实例对象
|
|
48
|
-
|
|
49
|
-
```typescript
|
|
50
|
-
// 获取现有的客户端实例
|
|
51
|
-
const existingClient = SmbClient.getInstance("my_client_id");
|
|
52
|
-
if (existingClient) {
|
|
53
|
-
await existingClient.listFiles("/");
|
|
54
|
-
}
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
### 5. `SmbClient.disposeAllClients()`
|
|
58
|
-
|
|
59
|
-
销毁所有客户端实例
|
|
60
|
-
|
|
61
|
-
```typescript
|
|
62
|
-
// 清理所有客户端
|
|
63
|
-
const disposedCount = await SmbClient.disposeAllClients();
|
|
64
|
-
console.log(`Disposed ${disposedCount} clients`);
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
## 使用示例
|
|
68
|
-
|
|
69
|
-
```typescript
|
|
70
|
-
import SmbClient from "react-native-kookit";
|
|
71
|
-
|
|
72
|
-
export class SmbManager {
|
|
73
|
-
private clients: Map<string, SmbClient> = new Map();
|
|
74
|
-
|
|
75
|
-
// 创建命名客户端
|
|
76
|
-
async createNamedClient(
|
|
77
|
-
name: string,
|
|
78
|
-
config: SmbConnectionConfig
|
|
79
|
-
): Promise<SmbClient> {
|
|
80
|
-
const client = await SmbClient.create(name);
|
|
81
|
-
await client.connect(config);
|
|
82
|
-
this.clients.set(name, client);
|
|
83
|
-
return client;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// 检查客户端是否存在且连接
|
|
87
|
-
isClientReady(name: string): boolean {
|
|
88
|
-
const status = SmbClient.getClientStatus(name);
|
|
89
|
-
return status.exists && status.isConnected && !status.isDisposed;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// 安全获取客户端
|
|
93
|
-
getClient(name: string): SmbClient | null {
|
|
94
|
-
if (this.isClientReady(name)) {
|
|
95
|
-
return SmbClient.getInstance(name);
|
|
96
|
-
}
|
|
97
|
-
return null;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// 销毁指定客户端
|
|
101
|
-
async removeClient(name: string): Promise<boolean> {
|
|
102
|
-
this.clients.delete(name);
|
|
103
|
-
return await SmbClient.disposeClient(name);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// 获取所有客户端状态报告
|
|
107
|
-
getStatusReport(): Record<string, any> {
|
|
108
|
-
const report: Record<string, any> = {};
|
|
109
|
-
const allStatus = SmbClient.getAllClientsStatus();
|
|
110
|
-
|
|
111
|
-
allStatus.forEach((status, clientId) => {
|
|
112
|
-
report[clientId] = {
|
|
113
|
-
...status,
|
|
114
|
-
managed: this.clients.has(clientId),
|
|
115
|
-
};
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
return report;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// 清理所有资源
|
|
122
|
-
async cleanup(): Promise<void> {
|
|
123
|
-
this.clients.clear();
|
|
124
|
-
await SmbClient.disposeAllClients();
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// 使用示例
|
|
129
|
-
const smbManager = new SmbManager();
|
|
130
|
-
|
|
131
|
-
// 创建多个客户端
|
|
132
|
-
const client1 = await smbManager.createNamedClient("server1", {
|
|
133
|
-
host: "192.168.1.100",
|
|
134
|
-
username: "user1",
|
|
135
|
-
password: "pass1",
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
const client2 = await smbManager.createNamedClient("server2", {
|
|
139
|
-
host: "192.168.1.101",
|
|
140
|
-
username: "user2",
|
|
141
|
-
password: "pass2",
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
// 检查状态
|
|
145
|
-
console.log("Status report:", smbManager.getStatusReport());
|
|
146
|
-
|
|
147
|
-
// 使用特定客户端
|
|
148
|
-
const client = smbManager.getClient("server1");
|
|
149
|
-
if (client) {
|
|
150
|
-
const files = await client.listFiles("/");
|
|
151
|
-
console.log("Files:", files);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// 清理资源
|
|
155
|
-
await smbManager.cleanup();
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
## 类型定义
|
|
159
|
-
|
|
160
|
-
```typescript
|
|
161
|
-
export interface SmbClientStatus {
|
|
162
|
-
exists: boolean;
|
|
163
|
-
isConnected: boolean;
|
|
164
|
-
currentShare: string | null;
|
|
165
|
-
isDisposed: boolean;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
export interface SmbClientInfo {
|
|
169
|
-
isConnected: boolean;
|
|
170
|
-
currentShare: string | null;
|
|
171
|
-
isDisposed: boolean;
|
|
172
|
-
}
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
这些静态方法使得SmbClient的多实例管理变得更加简单和安全。
|
package/SMB_COMPLETE_GUIDE.md
DELETED
|
@@ -1,308 +0,0 @@
|
|
|
1
|
-
# SMB Client Implementation
|
|
2
|
-
|
|
3
|
-
This document provides comprehensive documentation for the SMB client functionality in react-native-kookit.
|
|
4
|
-
|
|
5
|
-
## Overview
|
|
6
|
-
|
|
7
|
-
The SMB client provides object-oriented access to SMB/CIFS file shares, supporting both Android and iOS platforms with a unified API.
|
|
8
|
-
|
|
9
|
-
## Features
|
|
10
|
-
|
|
11
|
-
- **Object-oriented design**: Create multiple SMB client instances
|
|
12
|
-
- **Cross-platform**: Works on both Android and iOS
|
|
13
|
-
- **Progress tracking**: Real-time upload/download progress events
|
|
14
|
-
- **Full file operations**: List, download, upload, delete, create directories
|
|
15
|
-
- **Authentication**: Supports username/password and domain authentication
|
|
16
|
-
- **Share management**: Connect to different shares on the same server
|
|
17
|
-
|
|
18
|
-
## Platform Support
|
|
19
|
-
|
|
20
|
-
### Android
|
|
21
|
-
|
|
22
|
-
- Uses SMBJ library (version 0.13.0)
|
|
23
|
-
- Supports SMB2/3 protocols
|
|
24
|
-
- Full authentication and file operations
|
|
25
|
-
|
|
26
|
-
### iOS
|
|
27
|
-
|
|
28
|
-
- Uses SMBClient library (version 0.3.1)
|
|
29
|
-
- Supports SMB2 protocol
|
|
30
|
-
- Async/await Swift implementation
|
|
31
|
-
|
|
32
|
-
## API Reference
|
|
33
|
-
|
|
34
|
-
### Creating an SMB Client
|
|
35
|
-
|
|
36
|
-
```typescript
|
|
37
|
-
import { SmbClient } from "react-native-kookit";
|
|
38
|
-
|
|
39
|
-
// Create and initialize a new SMB client
|
|
40
|
-
const client = await SmbClient.create();
|
|
41
|
-
|
|
42
|
-
// Or create with custom client ID
|
|
43
|
-
const client = await SmbClient.create("my-smb-client");
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
### Connection Configuration
|
|
47
|
-
|
|
48
|
-
```typescript
|
|
49
|
-
interface SmbConnectionConfig {
|
|
50
|
-
host: string; // SMB server IP or hostname
|
|
51
|
-
port?: number; // Port (default: 445)
|
|
52
|
-
username: string; // Username for authentication
|
|
53
|
-
password: string; // Password for authentication
|
|
54
|
-
domain?: string; // Domain name (optional)
|
|
55
|
-
share?: string; // Share name to connect to (optional)
|
|
56
|
-
timeout?: number; // Connection timeout in milliseconds (default: 10000)
|
|
57
|
-
}
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
### Event Handlers
|
|
61
|
-
|
|
62
|
-
```typescript
|
|
63
|
-
client.setEventHandlers({
|
|
64
|
-
onProgress: (progress: {
|
|
65
|
-
transferred: number;
|
|
66
|
-
total: number;
|
|
67
|
-
percentage: number;
|
|
68
|
-
}) => {
|
|
69
|
-
console.log(`Progress: ${progress.percentage}%`);
|
|
70
|
-
},
|
|
71
|
-
onComplete: () => {
|
|
72
|
-
console.log("Operation completed");
|
|
73
|
-
},
|
|
74
|
-
onError: (error: Error) => {
|
|
75
|
-
console.error("SMB error:", error.message);
|
|
76
|
-
},
|
|
77
|
-
});
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
### Connection Methods
|
|
81
|
-
|
|
82
|
-
```typescript
|
|
83
|
-
// Connect to SMB server
|
|
84
|
-
await client.connect({
|
|
85
|
-
host: "192.168.1.100",
|
|
86
|
-
username: "admin",
|
|
87
|
-
password: "password",
|
|
88
|
-
domain: "WORKGROUP",
|
|
89
|
-
share: "shared",
|
|
90
|
-
timeout: 15000,
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
// Connect to a different share on the same server
|
|
94
|
-
await client.connectShare("documents");
|
|
95
|
-
|
|
96
|
-
// Disconnect from server
|
|
97
|
-
await client.disconnect();
|
|
98
|
-
|
|
99
|
-
// Dispose of the client (cleanup resources)
|
|
100
|
-
await client.dispose();
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
### File Operations
|
|
104
|
-
|
|
105
|
-
```typescript
|
|
106
|
-
// List files and directories
|
|
107
|
-
const files = await client.list("/path/to/directory");
|
|
108
|
-
console.log(files); // Array of SmbFileInfo objects
|
|
109
|
-
|
|
110
|
-
// Download a file
|
|
111
|
-
await client.download("/remote/file.txt", "/local/path/file.txt");
|
|
112
|
-
|
|
113
|
-
// Upload a file
|
|
114
|
-
await client.upload("/local/path/file.txt", "/remote/file.txt");
|
|
115
|
-
|
|
116
|
-
// Delete a file
|
|
117
|
-
await client.delete("/remote/file.txt");
|
|
118
|
-
|
|
119
|
-
// Delete a directory
|
|
120
|
-
await client.delete("/remote/directory", true);
|
|
121
|
-
|
|
122
|
-
// Create a directory
|
|
123
|
-
await client.createDirectory("/remote/new_directory");
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
### File Information Structure
|
|
127
|
-
|
|
128
|
-
```typescript
|
|
129
|
-
interface SmbFileInfo {
|
|
130
|
-
name: string; // File/directory name
|
|
131
|
-
isDirectory: boolean; // Whether it's a directory
|
|
132
|
-
size: number; // File size in bytes
|
|
133
|
-
lastModified: string; // Last modification date
|
|
134
|
-
attributes?: string; // File attributes (platform-specific)
|
|
135
|
-
}
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
### Client Management
|
|
139
|
-
|
|
140
|
-
```typescript
|
|
141
|
-
// Get client status
|
|
142
|
-
const status = await SmbClient.getClientStatus("client-id");
|
|
143
|
-
console.log(status); // { exists: boolean, connected: boolean }
|
|
144
|
-
|
|
145
|
-
// List all clients
|
|
146
|
-
const clients = await SmbClient.listClients();
|
|
147
|
-
console.log(clients); // { clients: Record<string, { connected: boolean }>, count: number }
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
## Usage Examples
|
|
151
|
-
|
|
152
|
-
### Basic Connection and File Listing
|
|
153
|
-
|
|
154
|
-
```typescript
|
|
155
|
-
import { SmbClient } from "react-native-kookit";
|
|
156
|
-
|
|
157
|
-
async function basicExample() {
|
|
158
|
-
const client = await SmbClient.create();
|
|
159
|
-
|
|
160
|
-
try {
|
|
161
|
-
await client.connect({
|
|
162
|
-
host: "192.168.1.100",
|
|
163
|
-
username: "admin",
|
|
164
|
-
password: "password",
|
|
165
|
-
share: "shared",
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
const files = await client.list();
|
|
169
|
-
files.forEach((file) => {
|
|
170
|
-
console.log(
|
|
171
|
-
`${file.isDirectory ? "📁" : "📄"} ${file.name} (${file.size} bytes)`
|
|
172
|
-
);
|
|
173
|
-
});
|
|
174
|
-
} catch (error) {
|
|
175
|
-
console.error("Error:", error.message);
|
|
176
|
-
} finally {
|
|
177
|
-
await client.dispose();
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
### File Upload with Progress
|
|
183
|
-
|
|
184
|
-
```typescript
|
|
185
|
-
async function uploadWithProgress() {
|
|
186
|
-
const client = await SmbClient.create();
|
|
187
|
-
|
|
188
|
-
client.setEventHandlers({
|
|
189
|
-
onProgress: (progress) => {
|
|
190
|
-
console.log(`Upload progress: ${progress.percentage}%`);
|
|
191
|
-
},
|
|
192
|
-
onComplete: () => {
|
|
193
|
-
console.log("Upload completed!");
|
|
194
|
-
},
|
|
195
|
-
onError: (error) => {
|
|
196
|
-
console.error("Upload failed:", error.message);
|
|
197
|
-
},
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
try {
|
|
201
|
-
await client.connect({
|
|
202
|
-
host: "192.168.1.100",
|
|
203
|
-
username: "admin",
|
|
204
|
-
password: "password",
|
|
205
|
-
share: "uploads",
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
await client.upload("/local/document.pdf", "/remote/backup/document.pdf");
|
|
209
|
-
} finally {
|
|
210
|
-
await client.dispose();
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
### Multiple Share Access
|
|
216
|
-
|
|
217
|
-
```typescript
|
|
218
|
-
async function multiShareExample() {
|
|
219
|
-
const client = await SmbClient.create();
|
|
220
|
-
|
|
221
|
-
try {
|
|
222
|
-
// Connect to server
|
|
223
|
-
await client.connect({
|
|
224
|
-
host: "192.168.1.100",
|
|
225
|
-
username: "admin",
|
|
226
|
-
password: "password",
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
// Connect to documents share
|
|
230
|
-
await client.connectShare("documents");
|
|
231
|
-
const docFiles = await client.list();
|
|
232
|
-
console.log("Documents:", docFiles.length, "files");
|
|
233
|
-
|
|
234
|
-
// Switch to media share
|
|
235
|
-
await client.connectShare("media");
|
|
236
|
-
const mediaFiles = await client.list();
|
|
237
|
-
console.log("Media:", mediaFiles.length, "files");
|
|
238
|
-
} finally {
|
|
239
|
-
await client.dispose();
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
## Error Handling
|
|
245
|
-
|
|
246
|
-
The SMB client throws specific errors for different scenarios:
|
|
247
|
-
|
|
248
|
-
```typescript
|
|
249
|
-
try {
|
|
250
|
-
await client.connect(config);
|
|
251
|
-
} catch (error) {
|
|
252
|
-
if (error.message.includes("SMB_CONNECT_ERROR")) {
|
|
253
|
-
// Handle connection errors
|
|
254
|
-
} else if (error.message.includes("SMB_AUTH_ERROR")) {
|
|
255
|
-
// Handle authentication errors
|
|
256
|
-
} else {
|
|
257
|
-
// Handle other errors
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
## Common Error Codes
|
|
263
|
-
|
|
264
|
-
- `SMB_CLIENT_EXISTS`: Client with the same ID already exists
|
|
265
|
-
- `SMB_CLIENT_NOT_FOUND`: Client ID not found
|
|
266
|
-
- `SMB_CONNECT_ERROR`: Connection failed
|
|
267
|
-
- `SMB_LIST_ERROR`: Failed to list directory
|
|
268
|
-
- `SMB_DOWNLOAD_ERROR`: Download operation failed
|
|
269
|
-
- `SMB_UPLOAD_ERROR`: Upload operation failed
|
|
270
|
-
- `SMB_DELETE_ERROR`: Delete operation failed
|
|
271
|
-
- `SMB_CREATE_DIR_ERROR`: Directory creation failed
|
|
272
|
-
|
|
273
|
-
## Best Practices
|
|
274
|
-
|
|
275
|
-
1. **Always dispose clients**: Use `try/finally` blocks to ensure proper cleanup
|
|
276
|
-
2. **Handle connection timeouts**: Set appropriate timeout values based on network conditions
|
|
277
|
-
3. **Use progress events**: Provide user feedback for long-running operations
|
|
278
|
-
4. **Error handling**: Implement comprehensive error handling for network operations
|
|
279
|
-
5. **Connection pooling**: Reuse client instances when possible to reduce overhead
|
|
280
|
-
|
|
281
|
-
## Troubleshooting
|
|
282
|
-
|
|
283
|
-
### Connection Issues
|
|
284
|
-
|
|
285
|
-
- Verify SMB server is accessible and SMB service is running
|
|
286
|
-
- Check firewall settings (default port 445)
|
|
287
|
-
- Ensure correct username/password credentials
|
|
288
|
-
- Try connecting without specifying a share first
|
|
289
|
-
|
|
290
|
-
### Authentication Problems
|
|
291
|
-
|
|
292
|
-
- Verify domain name is correct (or omit if not using domain)
|
|
293
|
-
- Check user permissions on the target share
|
|
294
|
-
- Some servers require specific SMB protocol versions
|
|
295
|
-
|
|
296
|
-
### File Operation Errors
|
|
297
|
-
|
|
298
|
-
- Ensure the share is properly connected before file operations
|
|
299
|
-
- Check file/directory permissions
|
|
300
|
-
- Verify paths use forward slashes (/) as separators
|
|
301
|
-
- Some special characters in filenames may cause issues
|
|
302
|
-
|
|
303
|
-
## Performance Considerations
|
|
304
|
-
|
|
305
|
-
- File operations are async and don't block the UI thread
|
|
306
|
-
- Large file transfers will trigger progress events for better UX
|
|
307
|
-
- Multiple concurrent operations on the same client are queued
|
|
308
|
-
- Consider using separate clients for parallel operations on different shares
|
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
# SMB 混合实现方案
|
|
2
|
-
|
|
3
|
-
## 概述
|
|
4
|
-
|
|
5
|
-
为了解决SMB share枚举的问题,我们实现了一个混合方案:
|
|
6
|
-
|
|
7
|
-
- 主要SMB客户端使用SMBJ(可靠性高)
|
|
8
|
-
- Share枚举使用JCIFS(功能更完整)
|
|
9
|
-
|
|
10
|
-
## 实现细节
|
|
11
|
-
|
|
12
|
-
### 1. 依赖库
|
|
13
|
-
|
|
14
|
-
- **SMBJ**: 主要SMB客户端操作(连接、文件操作等)
|
|
15
|
-
- **JCIFS**: Share枚举和发现(org.codelibs:jcifs:2.1.39)
|
|
16
|
-
|
|
17
|
-
### 2. 架构设计
|
|
18
|
-
|
|
19
|
-
#### SmbClient.kt 主类
|
|
20
|
-
|
|
21
|
-
- 保留SMBJ作为主要SMB客户端
|
|
22
|
-
- 添加JcifsShareEnumerator辅助类
|
|
23
|
-
- 存储连接凭据以供JCIFS使用
|
|
24
|
-
|
|
25
|
-
#### JcifsShareEnumerator.kt 辅助类
|
|
26
|
-
|
|
27
|
-
- 专门用于Share枚举
|
|
28
|
-
- 使用JCIFS进行完整的Share发现
|
|
29
|
-
- 提供连接测试功能
|
|
30
|
-
|
|
31
|
-
### 3. listShares() 方法流程
|
|
32
|
-
|
|
33
|
-
```kotlin
|
|
34
|
-
fun listShares(): List<String> {
|
|
35
|
-
// 1. 尝试使用JCIFS进行完整Share枚举
|
|
36
|
-
try {
|
|
37
|
-
val shares = jcifsEnumerator.listShares(host, username, password, domain)
|
|
38
|
-
if (shares.isNotEmpty()) {
|
|
39
|
-
return shares
|
|
40
|
-
}
|
|
41
|
-
} catch (e: Exception) {
|
|
42
|
-
// 继续到fallback方法
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// 2. Fallback: 使用SMBJ测试常见Share名称
|
|
46
|
-
try {
|
|
47
|
-
// 测试常见Windows和用户定义的Share
|
|
48
|
-
val commonShares = listOf("C$", "D$", "shared", "public", ...)
|
|
49
|
-
// 返回可访问的Share
|
|
50
|
-
} catch (e: Exception) {
|
|
51
|
-
// 最终fallback: 返回常见Share名称
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
### 4. 优势
|
|
57
|
-
|
|
58
|
-
1. **可靠性**: SMBJ作为主要客户端,稳定性高
|
|
59
|
-
2. **完整性**: JCIFS提供完整的Share枚举
|
|
60
|
-
3. **容错性**: 多层fallback机制
|
|
61
|
-
4. **性能**: JCIFS仅用于Share枚举,不影响主要操作
|
|
62
|
-
|
|
63
|
-
### 5. Share参数说明
|
|
64
|
-
|
|
65
|
-
#### 对于列出SMB根目录(Share根目录):
|
|
66
|
-
|
|
67
|
-
```typescript
|
|
68
|
-
// 连接到具体Share
|
|
69
|
-
await smbClient.connect({
|
|
70
|
-
host: "192.168.1.100",
|
|
71
|
-
username: "user",
|
|
72
|
-
password: "pass",
|
|
73
|
-
share: "C$", // 指定具体的Share
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
// 列出Share根目录
|
|
77
|
-
const files = await smbClient.listFiles(""); // 空字符串表示Share根目录
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
#### 对于列出所有可用Share:
|
|
81
|
-
|
|
82
|
-
```typescript
|
|
83
|
-
// 只需要认证,不指定share
|
|
84
|
-
await smbClient.connect({
|
|
85
|
-
host: "192.168.1.100",
|
|
86
|
-
username: "user",
|
|
87
|
-
password: "pass",
|
|
88
|
-
// 不指定share参数
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
// 获取所有可用Share
|
|
92
|
-
const shares = await smbClient.listShares();
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
### 6. 常见Share类型
|
|
96
|
-
|
|
97
|
-
#### Windows系统Share:
|
|
98
|
-
|
|
99
|
-
- `C$`, `D$`, `E$`: 驱动器共享(需要管理员权限)
|
|
100
|
-
- `ADMIN$`: 管理共享
|
|
101
|
-
- `IPC$`: 进程间通信共享
|
|
102
|
-
|
|
103
|
-
#### 用户定义Share:
|
|
104
|
-
|
|
105
|
-
- `shared`, `public`, `data`: 常见的用户共享文件夹
|
|
106
|
-
- `home`, `Users`: 用户目录共享
|
|
107
|
-
- `documents`, `media`: 媒体和文档共享
|
|
108
|
-
|
|
109
|
-
## 使用示例
|
|
110
|
-
|
|
111
|
-
```typescript
|
|
112
|
-
const smbClient = new SmbClient();
|
|
113
|
-
|
|
114
|
-
// 1. 连接到服务器
|
|
115
|
-
await smbClient.connect({
|
|
116
|
-
host: "192.168.1.100",
|
|
117
|
-
username: "myuser",
|
|
118
|
-
password: "mypass",
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
// 2. 获取所有可用Share
|
|
122
|
-
const shares = await smbClient.listShares();
|
|
123
|
-
console.log("Available shares:", shares);
|
|
124
|
-
// 输出: ['C$', 'shared', 'public', 'documents']
|
|
125
|
-
|
|
126
|
-
// 3. 连接到具体Share
|
|
127
|
-
await smbClient.openShare("shared");
|
|
128
|
-
|
|
129
|
-
// 4. 列出Share根目录
|
|
130
|
-
const files = await smbClient.listFiles("");
|
|
131
|
-
|
|
132
|
-
// 5. 列出子目录
|
|
133
|
-
const subFiles = await smbClient.listFiles("subfolder");
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
## 故障排除
|
|
137
|
-
|
|
138
|
-
### 如果JCIFS枚举失败:
|
|
139
|
-
|
|
140
|
-
- 自动fallback到SMBJ测试方法
|
|
141
|
-
- 返回测试可访问的常见Share
|
|
142
|
-
|
|
143
|
-
### 如果所有方法都失败:
|
|
144
|
-
|
|
145
|
-
- 返回最常见的Share名称列表
|
|
146
|
-
- 用户可以手动尝试连接
|
|
147
|
-
|
|
148
|
-
## 技术细节
|
|
149
|
-
|
|
150
|
-
### JCIFS配置:
|
|
151
|
-
|
|
152
|
-
- 使用NtlmPasswordAuthenticator进行认证
|
|
153
|
-
- 通过SmbFile访问服务器根目录
|
|
154
|
-
- 枚举所有可用的Share
|
|
155
|
-
|
|
156
|
-
### SMBJ fallback:
|
|
157
|
-
|
|
158
|
-
- 测试常见Share名称的可访问性
|
|
159
|
-
- 短暂连接后立即关闭以测试可用性
|
|
160
|
-
- 收集所有可访问的Share名称
|