@capgo/capacitor-uploader 8.3.0 → 8.3.2
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 +36 -0
- package/android/src/main/java/ee/forgr/capacitor/uploader/Uploader.java +140 -26
- package/android/src/main/java/ee/forgr/capacitor/uploader/UploaderPlugin.java +46 -3
- package/dist/docs.json +113 -0
- package/dist/esm/definitions.d.ts +67 -0
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/web.d.ts +4 -1
- package/dist/esm/web.js +12 -0
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +12 -0
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +12 -0
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/UploaderPlugin/UploaderPlugin.swift +36 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -256,6 +256,7 @@ Documentation for the [Capacitor Camera preview](https://github.com/Cap-go/camer
|
|
|
256
256
|
<docgen-index>
|
|
257
257
|
|
|
258
258
|
* [`startUpload(...)`](#startupload)
|
|
259
|
+
* [`uploadMultipart(...)`](#uploadmultipart)
|
|
259
260
|
* [`removeUpload(...)`](#removeupload)
|
|
260
261
|
* [`addListener('events', ...)`](#addlistenerevents-)
|
|
261
262
|
* [`acknowledgeEvent(...)`](#acknowledgeevent)
|
|
@@ -305,6 +306,28 @@ Listen to upload events to track progress, completion, or failure.
|
|
|
305
306
|
--------------------
|
|
306
307
|
|
|
307
308
|
|
|
309
|
+
### uploadMultipart(...)
|
|
310
|
+
|
|
311
|
+
```typescript
|
|
312
|
+
uploadMultipart(options: UploadMultipartOptions) => Promise<{ id: string; }>
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
Start uploading a single file as multipart/form-data.
|
|
316
|
+
|
|
317
|
+
This is a convenience API for backends that expect a named file field and
|
|
318
|
+
additional form fields. Existing `startUpload` binary uploads are unchanged.
|
|
319
|
+
|
|
320
|
+
| Param | Type | Description |
|
|
321
|
+
| ------------- | ------------------------------------------------------------------------- | ---------------------------------------- |
|
|
322
|
+
| **`options`** | <code><a href="#uploadmultipartoptions">UploadMultipartOptions</a></code> | - Configuration for the multipart upload |
|
|
323
|
+
|
|
324
|
+
**Returns:** <code>Promise<{ id: string; }></code>
|
|
325
|
+
|
|
326
|
+
**Since:** 8.3.2
|
|
327
|
+
|
|
328
|
+
--------------------
|
|
329
|
+
|
|
330
|
+
|
|
308
331
|
### removeUpload(...)
|
|
309
332
|
|
|
310
333
|
```typescript
|
|
@@ -419,6 +442,19 @@ Configuration options for uploading a file.
|
|
|
419
442
|
| **`mimeType`** | <code>string</code> | The MIME type of this file. If not specified, the plugin will attempt to determine it automatically. | 0.0.3 |
|
|
420
443
|
|
|
421
444
|
|
|
445
|
+
#### UploadMultipartOptions
|
|
446
|
+
|
|
447
|
+
Options for starting a single-file multipart upload.
|
|
448
|
+
|
|
449
|
+
| Prop | Type | Description | Since |
|
|
450
|
+
| --------------- | --------------------------------------- | ------------------------------------------------------------------------------------ | ----- |
|
|
451
|
+
| **`url`** | <code>string</code> | The server URL endpoint where the multipart request should be sent. | 8.3.2 |
|
|
452
|
+
| **`filePath`** | <code>string</code> | The local file path of the file to upload. Can be a file:// URL or an absolute path. | 8.3.2 |
|
|
453
|
+
| **`fieldName`** | <code>string</code> | The form field name for the uploaded file part. | 8.3.2 |
|
|
454
|
+
| **`fields`** | <code>{ [key: string]: string; }</code> | Additional form fields to include in the multipart request. | 8.3.2 |
|
|
455
|
+
| **`headers`** | <code>{ [key: string]: string; }</code> | HTTP headers to send with the upload request. | 8.3.2 |
|
|
456
|
+
|
|
457
|
+
|
|
422
458
|
#### PluginListenerHandle
|
|
423
459
|
|
|
424
460
|
| Prop | Type |
|
|
@@ -5,17 +5,29 @@ import android.content.Context;
|
|
|
5
5
|
import android.database.Cursor;
|
|
6
6
|
import android.net.Uri;
|
|
7
7
|
import android.provider.OpenableColumns;
|
|
8
|
+
import java.io.File;
|
|
9
|
+
import java.io.FileInputStream;
|
|
10
|
+
import java.io.FileNotFoundException;
|
|
11
|
+
import java.io.FileOutputStream;
|
|
12
|
+
import java.io.IOException;
|
|
13
|
+
import java.io.InputStream;
|
|
14
|
+
import java.io.OutputStream;
|
|
15
|
+
import java.nio.charset.StandardCharsets;
|
|
8
16
|
import java.util.List;
|
|
9
17
|
import java.util.Map;
|
|
18
|
+
import java.util.UUID;
|
|
19
|
+
import java.util.concurrent.ConcurrentHashMap;
|
|
10
20
|
import net.gotev.uploadservice.UploadServiceConfig;
|
|
11
21
|
import net.gotev.uploadservice.data.UploadNotificationConfig;
|
|
12
22
|
import net.gotev.uploadservice.data.UploadNotificationStatusConfig;
|
|
13
23
|
import net.gotev.uploadservice.protocols.binary.BinaryUploadRequest;
|
|
14
|
-
import net.gotev.uploadservice.protocols.multipart.MultipartUploadRequest;
|
|
15
24
|
|
|
16
25
|
public class Uploader {
|
|
17
26
|
|
|
27
|
+
private static final int STREAM_BUFFER_SIZE = 64 * 1024;
|
|
28
|
+
|
|
18
29
|
private final Context context;
|
|
30
|
+
private final Map<String, File> tempMultipartBodies = new ConcurrentHashMap<>();
|
|
19
31
|
|
|
20
32
|
public static class UploadFile {
|
|
21
33
|
|
|
@@ -70,31 +82,7 @@ public class Uploader {
|
|
|
70
82
|
if (files == null || files.isEmpty()) {
|
|
71
83
|
throw new IllegalArgumentException("Missing required parameter: files");
|
|
72
84
|
}
|
|
73
|
-
|
|
74
|
-
.setMethod(httpMethod)
|
|
75
|
-
.setNotificationConfig((ctx, uploadId) -> notificationConfig)
|
|
76
|
-
.setMaxRetries(maxRetries);
|
|
77
|
-
|
|
78
|
-
for (UploadFile file : files) {
|
|
79
|
-
if (file == null || file.filePath == null || file.filePath.isEmpty()) {
|
|
80
|
-
throw new IllegalArgumentException("Invalid file entry in files");
|
|
81
|
-
}
|
|
82
|
-
String fieldName = (file.fieldName == null || file.fieldName.isEmpty()) ? "file" : file.fieldName;
|
|
83
|
-
request.addFileToUpload(file.filePath, fieldName, getFileNameFromUri(Uri.parse(file.filePath)), file.mimeType);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
for (Map.Entry<String, String> entry : headers.entrySet()) {
|
|
87
|
-
if (entry.getKey() != null && entry.getValue() != null) {
|
|
88
|
-
request.addHeader(entry.getKey(), entry.getValue());
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
for (Map.Entry<String, String> entry : parameters.entrySet()) {
|
|
92
|
-
if (entry.getKey() != null && entry.getValue() != null) {
|
|
93
|
-
request.addParameter(entry.getKey(), entry.getValue());
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
return request.startUpload();
|
|
85
|
+
return startMultipartUpload(files, serverUrl, headers, parameters, httpMethod, notificationConfig, maxRetries);
|
|
98
86
|
} else {
|
|
99
87
|
if (files == null || files.isEmpty()) {
|
|
100
88
|
throw new IllegalArgumentException("Missing required parameter: filePath or files");
|
|
@@ -116,6 +104,131 @@ public class Uploader {
|
|
|
116
104
|
}
|
|
117
105
|
}
|
|
118
106
|
|
|
107
|
+
private String startMultipartUpload(
|
|
108
|
+
List<UploadFile> files,
|
|
109
|
+
String serverUrl,
|
|
110
|
+
Map<String, String> headers,
|
|
111
|
+
Map<String, String> parameters,
|
|
112
|
+
String httpMethod,
|
|
113
|
+
UploadNotificationConfig notificationConfig,
|
|
114
|
+
int maxRetries
|
|
115
|
+
) throws Exception {
|
|
116
|
+
String boundary = UUID.randomUUID().toString();
|
|
117
|
+
File tempBody = writeMultipartBodyToFile(files, parameters, boundary);
|
|
118
|
+
|
|
119
|
+
try {
|
|
120
|
+
BinaryUploadRequest request = new BinaryUploadRequest(context, serverUrl)
|
|
121
|
+
.setMethod(httpMethod)
|
|
122
|
+
.setFileToUpload(tempBody.getAbsolutePath())
|
|
123
|
+
.setNotificationConfig((ctx, uploadId) -> notificationConfig)
|
|
124
|
+
.setMaxRetries(maxRetries)
|
|
125
|
+
.setUsesFixedLengthStreamingMode(true);
|
|
126
|
+
|
|
127
|
+
request.addHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
|
|
128
|
+
|
|
129
|
+
for (Map.Entry<String, String> entry : headers.entrySet()) {
|
|
130
|
+
if (entry.getKey() != null && entry.getValue() != null) {
|
|
131
|
+
request.addHeader(entry.getKey(), entry.getValue());
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
String uploadId = request.startUpload();
|
|
136
|
+
tempMultipartBodies.put(uploadId, tempBody);
|
|
137
|
+
return uploadId;
|
|
138
|
+
} catch (Exception e) {
|
|
139
|
+
if (!tempBody.delete()) {
|
|
140
|
+
tempBody.deleteOnExit();
|
|
141
|
+
}
|
|
142
|
+
throw e;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
private File writeMultipartBodyToFile(List<UploadFile> files, Map<String, String> parameters, String boundary) throws IOException {
|
|
147
|
+
File tempFile = File.createTempFile("upload-", ".tmp", context.getCacheDir());
|
|
148
|
+
|
|
149
|
+
try (FileOutputStream output = new FileOutputStream(tempFile)) {
|
|
150
|
+
if (parameters != null) {
|
|
151
|
+
for (Map.Entry<String, String> entry : parameters.entrySet()) {
|
|
152
|
+
if (entry.getKey() == null || entry.getValue() == null) {
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
writeUtf8(output, "--" + boundary + "\r\n");
|
|
156
|
+
writeUtf8(output, "Content-Disposition: form-data; name=\"" + entry.getKey() + "\"\r\n\r\n");
|
|
157
|
+
writeUtf8(output, entry.getValue() + "\r\n");
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
for (UploadFile file : files) {
|
|
162
|
+
if (file == null || file.filePath == null || file.filePath.isEmpty()) {
|
|
163
|
+
throw new IllegalArgumentException("Invalid file entry in files");
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
String fieldName = (file.fieldName == null || file.fieldName.isEmpty()) ? "file" : file.fieldName;
|
|
167
|
+
String fileName = getFileNameFromUri(Uri.parse(file.filePath));
|
|
168
|
+
if (fileName == null || fileName.isEmpty()) {
|
|
169
|
+
fileName = "file";
|
|
170
|
+
}
|
|
171
|
+
String mimeType = (file.mimeType == null || file.mimeType.isEmpty()) ? "application/octet-stream" : file.mimeType;
|
|
172
|
+
|
|
173
|
+
writeUtf8(output, "--" + boundary + "\r\n");
|
|
174
|
+
writeUtf8(output, "Content-Disposition: form-data; name=\"" + fieldName + "\"; filename=\"" + fileName + "\"\r\n");
|
|
175
|
+
writeUtf8(output, "Content-Type: " + mimeType + "\r\n\r\n");
|
|
176
|
+
streamFileToOutput(file.filePath, output);
|
|
177
|
+
writeUtf8(output, "\r\n");
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
writeUtf8(output, "--" + boundary + "--\r\n");
|
|
181
|
+
} catch (IOException | RuntimeException e) {
|
|
182
|
+
if (!tempFile.delete()) {
|
|
183
|
+
tempFile.deleteOnExit();
|
|
184
|
+
}
|
|
185
|
+
throw e;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return tempFile;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
private void writeUtf8(OutputStream output, String value) throws IOException {
|
|
192
|
+
output.write(value.getBytes(StandardCharsets.UTF_8));
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
private void streamFileToOutput(String filePath, OutputStream output) throws IOException {
|
|
196
|
+
try (InputStream input = openInputStream(filePath)) {
|
|
197
|
+
byte[] buffer = new byte[STREAM_BUFFER_SIZE];
|
|
198
|
+
int read;
|
|
199
|
+
while ((read = input.read(buffer)) != -1) {
|
|
200
|
+
output.write(buffer, 0, read);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
private InputStream openInputStream(String filePath) throws IOException {
|
|
206
|
+
if (filePath.startsWith("content://")) {
|
|
207
|
+
InputStream stream = context.getContentResolver().openInputStream(Uri.parse(filePath));
|
|
208
|
+
if (stream == null) {
|
|
209
|
+
throw new FileNotFoundException("Cannot open content URI: " + filePath);
|
|
210
|
+
}
|
|
211
|
+
return stream;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (filePath.startsWith("file://")) {
|
|
215
|
+
String path = Uri.parse(filePath).getPath();
|
|
216
|
+
if (path == null) {
|
|
217
|
+
throw new FileNotFoundException("Invalid file URI: " + filePath);
|
|
218
|
+
}
|
|
219
|
+
return new FileInputStream(path);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return new FileInputStream(filePath);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
public void clearTempMultipartBody(String uploadId) {
|
|
226
|
+
File tempFile = tempMultipartBodies.remove(uploadId);
|
|
227
|
+
if (tempFile != null && !tempFile.delete()) {
|
|
228
|
+
tempFile.deleteOnExit();
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
119
232
|
private String startBinaryUpload(
|
|
120
233
|
String filePath,
|
|
121
234
|
String serverUrl,
|
|
@@ -152,6 +265,7 @@ public class Uploader {
|
|
|
152
265
|
}
|
|
153
266
|
|
|
154
267
|
public void removeUpload(String uploadId) {
|
|
268
|
+
clearTempMultipartBody(uploadId);
|
|
155
269
|
net.gotev.uploadservice.UploadService.stopUpload(uploadId);
|
|
156
270
|
}
|
|
157
271
|
|
|
@@ -33,7 +33,7 @@ public class UploaderPlugin extends Plugin {
|
|
|
33
33
|
|
|
34
34
|
private static final String CAPACITOR_CONTENT_PATH_PREFIX = "/_capacitor_content_";
|
|
35
35
|
|
|
36
|
-
private final String pluginVersion = "8.3.
|
|
36
|
+
private final String pluginVersion = "8.3.2";
|
|
37
37
|
|
|
38
38
|
private Uploader implementation;
|
|
39
39
|
|
|
@@ -119,6 +119,7 @@ public class UploaderPlugin extends Plugin {
|
|
|
119
119
|
|
|
120
120
|
@Override
|
|
121
121
|
public void onSuccess(Context context, UploadInfo uploadInfo, ServerResponse serverResponse) {
|
|
122
|
+
implementation.clearTempMultipartBody(uploadInfo.getUploadId());
|
|
122
123
|
JSObject event = new JSObject();
|
|
123
124
|
event.put("name", "completed");
|
|
124
125
|
JSObject payload = new JSObject();
|
|
@@ -133,6 +134,7 @@ public class UploaderPlugin extends Plugin {
|
|
|
133
134
|
|
|
134
135
|
@Override
|
|
135
136
|
public void onError(Context context, UploadInfo uploadInfo, Throwable exception) {
|
|
137
|
+
implementation.clearTempMultipartBody(uploadInfo.getUploadId());
|
|
136
138
|
JSObject event = new JSObject();
|
|
137
139
|
event.put("name", "failed");
|
|
138
140
|
JSObject payload = new JSObject();
|
|
@@ -147,6 +149,7 @@ public class UploaderPlugin extends Plugin {
|
|
|
147
149
|
|
|
148
150
|
@Override
|
|
149
151
|
public void onCompleted(Context context, UploadInfo uploadInfo) {
|
|
152
|
+
implementation.clearTempMultipartBody(uploadInfo.getUploadId());
|
|
150
153
|
JSObject event = new JSObject();
|
|
151
154
|
event.put("name", "finished");
|
|
152
155
|
event.put("id", uploadInfo.getUploadId());
|
|
@@ -255,6 +258,46 @@ public class UploaderPlugin extends Plugin {
|
|
|
255
258
|
}
|
|
256
259
|
}
|
|
257
260
|
|
|
261
|
+
@PluginMethod
|
|
262
|
+
public void uploadMultipart(PluginCall call) {
|
|
263
|
+
String serverUrl = call.getString("url");
|
|
264
|
+
if (serverUrl == null || serverUrl.isEmpty()) {
|
|
265
|
+
call.reject("Missing required parameter: url");
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
String filePath = call.getString("filePath");
|
|
270
|
+
if (filePath == null || filePath.isEmpty()) {
|
|
271
|
+
call.reject("Missing required parameter: filePath");
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
String fieldName = call.getString("fieldName");
|
|
276
|
+
if (fieldName == null || fieldName.isEmpty()) {
|
|
277
|
+
call.reject("Missing required parameter: fieldName");
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
JSObject headersObj = call.getObject("headers", new JSObject());
|
|
282
|
+
JSObject fieldsObj = call.getObject("fields", new JSObject());
|
|
283
|
+
Map<String, String> headers = JSObjectToMap(headersObj);
|
|
284
|
+
Map<String, String> fields = JSObjectToMap(fieldsObj);
|
|
285
|
+
|
|
286
|
+
try {
|
|
287
|
+
String localFilePath = resolveCapacitorPath(filePath);
|
|
288
|
+
String mimeType = getMimeType(localFilePath);
|
|
289
|
+
ArrayList<Uploader.UploadFile> filesToUpload = new ArrayList<>();
|
|
290
|
+
filesToUpload.add(new Uploader.UploadFile(localFilePath, fieldName, mimeType));
|
|
291
|
+
|
|
292
|
+
String id = implementation.startUpload(filesToUpload, serverUrl, headers, fields, "POST", "File Upload", 2, "multipart");
|
|
293
|
+
JSObject result = new JSObject();
|
|
294
|
+
result.put("id", id);
|
|
295
|
+
call.resolve(result);
|
|
296
|
+
} catch (Exception e) {
|
|
297
|
+
call.reject(e.getMessage());
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
258
301
|
@PluginMethod
|
|
259
302
|
public void removeUpload(PluginCall call) {
|
|
260
303
|
String id = call.getString("id");
|
|
@@ -293,9 +336,9 @@ public class UploaderPlugin extends Plugin {
|
|
|
293
336
|
if (uri.getPort() != -1) {
|
|
294
337
|
baseUrl += ":" + uri.getPort();
|
|
295
338
|
}
|
|
296
|
-
return filePath.replace(baseUrl + CAPACITOR_CONTENT_PATH_PREFIX, "content
|
|
339
|
+
return filePath.replace(baseUrl + CAPACITOR_CONTENT_PATH_PREFIX, "content://");
|
|
297
340
|
}
|
|
298
|
-
return filePath.replace(CAPACITOR_CONTENT_PATH_PREFIX, "content
|
|
341
|
+
return filePath.replace(CAPACITOR_CONTENT_PATH_PREFIX, "content://");
|
|
299
342
|
}
|
|
300
343
|
}
|
|
301
344
|
if ("file".equalsIgnoreCase(uri.getScheme()) && uri.getPath() != null) {
|
package/dist/docs.json
CHANGED
|
@@ -57,6 +57,45 @@
|
|
|
57
57
|
],
|
|
58
58
|
"slug": "startupload"
|
|
59
59
|
},
|
|
60
|
+
{
|
|
61
|
+
"name": "uploadMultipart",
|
|
62
|
+
"signature": "(options: UploadMultipartOptions) => Promise<{ id: string; }>",
|
|
63
|
+
"parameters": [
|
|
64
|
+
{
|
|
65
|
+
"name": "options",
|
|
66
|
+
"docs": "- Configuration for the multipart upload",
|
|
67
|
+
"type": "UploadMultipartOptions"
|
|
68
|
+
}
|
|
69
|
+
],
|
|
70
|
+
"returns": "Promise<{ id: string; }>",
|
|
71
|
+
"tags": [
|
|
72
|
+
{
|
|
73
|
+
"name": "param",
|
|
74
|
+
"text": "options - Configuration for the multipart upload"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"name": "returns",
|
|
78
|
+
"text": "Promise that resolves with the upload ID"
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"name": "throws",
|
|
82
|
+
"text": "Error if the upload fails to start"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"name": "since",
|
|
86
|
+
"text": "8.3.2"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"name": "example",
|
|
90
|
+
"text": "```typescript\nconst { id } = await Uploader.uploadMultipart({\n url: 'https://example.com/upload',\n filePath: 'file:///path/to/file.jpg',\n fieldName: 'photo',\n fields: { albumId: '7' },\n headers: { Authorization: 'Bearer token' },\n});\nconsole.log('Upload started with ID:', id);\n```"
|
|
91
|
+
}
|
|
92
|
+
],
|
|
93
|
+
"docs": "Start uploading a single file as multipart/form-data.\n\nThis is a convenience API for backends that expect a named file field and\nadditional form fields. Existing `startUpload` binary uploads are unchanged.",
|
|
94
|
+
"complexTypes": [
|
|
95
|
+
"UploadMultipartOptions"
|
|
96
|
+
],
|
|
97
|
+
"slug": "uploadmultipart"
|
|
98
|
+
},
|
|
60
99
|
{
|
|
61
100
|
"name": "removeUpload",
|
|
62
101
|
"signature": "(options: { id: string; }) => Promise<void>",
|
|
@@ -424,6 +463,80 @@
|
|
|
424
463
|
}
|
|
425
464
|
]
|
|
426
465
|
},
|
|
466
|
+
{
|
|
467
|
+
"name": "UploadMultipartOptions",
|
|
468
|
+
"slug": "uploadmultipartoptions",
|
|
469
|
+
"docs": "Options for starting a single-file multipart upload.",
|
|
470
|
+
"tags": [
|
|
471
|
+
{
|
|
472
|
+
"text": "8.3.2",
|
|
473
|
+
"name": "since"
|
|
474
|
+
}
|
|
475
|
+
],
|
|
476
|
+
"methods": [],
|
|
477
|
+
"properties": [
|
|
478
|
+
{
|
|
479
|
+
"name": "url",
|
|
480
|
+
"tags": [
|
|
481
|
+
{
|
|
482
|
+
"text": "8.3.2",
|
|
483
|
+
"name": "since"
|
|
484
|
+
}
|
|
485
|
+
],
|
|
486
|
+
"docs": "The server URL endpoint where the multipart request should be sent.",
|
|
487
|
+
"complexTypes": [],
|
|
488
|
+
"type": "string"
|
|
489
|
+
},
|
|
490
|
+
{
|
|
491
|
+
"name": "filePath",
|
|
492
|
+
"tags": [
|
|
493
|
+
{
|
|
494
|
+
"text": "8.3.2",
|
|
495
|
+
"name": "since"
|
|
496
|
+
}
|
|
497
|
+
],
|
|
498
|
+
"docs": "The local file path of the file to upload.\nCan be a file:// URL or an absolute path.",
|
|
499
|
+
"complexTypes": [],
|
|
500
|
+
"type": "string"
|
|
501
|
+
},
|
|
502
|
+
{
|
|
503
|
+
"name": "fieldName",
|
|
504
|
+
"tags": [
|
|
505
|
+
{
|
|
506
|
+
"text": "8.3.2",
|
|
507
|
+
"name": "since"
|
|
508
|
+
}
|
|
509
|
+
],
|
|
510
|
+
"docs": "The form field name for the uploaded file part.",
|
|
511
|
+
"complexTypes": [],
|
|
512
|
+
"type": "string"
|
|
513
|
+
},
|
|
514
|
+
{
|
|
515
|
+
"name": "fields",
|
|
516
|
+
"tags": [
|
|
517
|
+
{
|
|
518
|
+
"text": "8.3.2",
|
|
519
|
+
"name": "since"
|
|
520
|
+
}
|
|
521
|
+
],
|
|
522
|
+
"docs": "Additional form fields to include in the multipart request.",
|
|
523
|
+
"complexTypes": [],
|
|
524
|
+
"type": "{ [key: string]: string; } | undefined"
|
|
525
|
+
},
|
|
526
|
+
{
|
|
527
|
+
"name": "headers",
|
|
528
|
+
"tags": [
|
|
529
|
+
{
|
|
530
|
+
"text": "8.3.2",
|
|
531
|
+
"name": "since"
|
|
532
|
+
}
|
|
533
|
+
],
|
|
534
|
+
"docs": "HTTP headers to send with the upload request.",
|
|
535
|
+
"complexTypes": [],
|
|
536
|
+
"type": "{ [key: string]: string; } | undefined"
|
|
537
|
+
}
|
|
538
|
+
]
|
|
539
|
+
},
|
|
427
540
|
{
|
|
428
541
|
"name": "PluginListenerHandle",
|
|
429
542
|
"slug": "pluginlistenerhandle",
|
|
@@ -28,6 +28,48 @@ export interface UploadFileOption {
|
|
|
28
28
|
*/
|
|
29
29
|
mimeType?: string;
|
|
30
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Options for starting a single-file multipart upload.
|
|
33
|
+
*
|
|
34
|
+
* @since 8.3.2
|
|
35
|
+
*/
|
|
36
|
+
export interface UploadMultipartOptions {
|
|
37
|
+
/**
|
|
38
|
+
* The server URL endpoint where the multipart request should be sent.
|
|
39
|
+
*
|
|
40
|
+
* @since 8.3.2
|
|
41
|
+
*/
|
|
42
|
+
url: string;
|
|
43
|
+
/**
|
|
44
|
+
* The local file path of the file to upload.
|
|
45
|
+
* Can be a file:// URL or an absolute path.
|
|
46
|
+
*
|
|
47
|
+
* @since 8.3.2
|
|
48
|
+
*/
|
|
49
|
+
filePath: string;
|
|
50
|
+
/**
|
|
51
|
+
* The form field name for the uploaded file part.
|
|
52
|
+
*
|
|
53
|
+
* @since 8.3.2
|
|
54
|
+
*/
|
|
55
|
+
fieldName: string;
|
|
56
|
+
/**
|
|
57
|
+
* Additional form fields to include in the multipart request.
|
|
58
|
+
*
|
|
59
|
+
* @since 8.3.2
|
|
60
|
+
*/
|
|
61
|
+
fields?: {
|
|
62
|
+
[key: string]: string;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* HTTP headers to send with the upload request.
|
|
66
|
+
*
|
|
67
|
+
* @since 8.3.2
|
|
68
|
+
*/
|
|
69
|
+
headers?: {
|
|
70
|
+
[key: string]: string;
|
|
71
|
+
};
|
|
72
|
+
}
|
|
31
73
|
export interface uploadOption {
|
|
32
74
|
/**
|
|
33
75
|
* The local file path of the file to upload.
|
|
@@ -266,6 +308,31 @@ export interface UploaderPlugin {
|
|
|
266
308
|
startUpload(options: uploadOption): Promise<{
|
|
267
309
|
id: string;
|
|
268
310
|
}>;
|
|
311
|
+
/**
|
|
312
|
+
* Start uploading a single file as multipart/form-data.
|
|
313
|
+
*
|
|
314
|
+
* This is a convenience API for backends that expect a named file field and
|
|
315
|
+
* additional form fields. Existing `startUpload` binary uploads are unchanged.
|
|
316
|
+
*
|
|
317
|
+
* @param options - Configuration for the multipart upload
|
|
318
|
+
* @returns Promise that resolves with the upload ID
|
|
319
|
+
* @throws Error if the upload fails to start
|
|
320
|
+
* @since 8.3.2
|
|
321
|
+
* @example
|
|
322
|
+
* ```typescript
|
|
323
|
+
* const { id } = await Uploader.uploadMultipart({
|
|
324
|
+
* url: 'https://example.com/upload',
|
|
325
|
+
* filePath: 'file:///path/to/file.jpg',
|
|
326
|
+
* fieldName: 'photo',
|
|
327
|
+
* fields: { albumId: '7' },
|
|
328
|
+
* headers: { Authorization: 'Bearer token' },
|
|
329
|
+
* });
|
|
330
|
+
* console.log('Upload started with ID:', id);
|
|
331
|
+
* ```
|
|
332
|
+
*/
|
|
333
|
+
uploadMultipart(options: UploadMultipartOptions): Promise<{
|
|
334
|
+
id: string;
|
|
335
|
+
}>;
|
|
269
336
|
/**
|
|
270
337
|
* Cancel and remove an ongoing upload.
|
|
271
338
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["import type { PluginListenerHandle } from '@capacitor/core';\n\n/**\n * Configuration options for uploading a file.\n *\n * @since 0.0.1\n */\nexport interface UploadFileOption {\n /**\n * The local file path of the file to upload.\n * Can be a file:// URL or an absolute path.\n *\n * @since 0.0.3\n */\n filePath: string;\n\n /**\n * The form field name for the file part when using multipart upload.\n *\n * If omitted, `uploadOption.fileField` is used (defaults to `'file'`).\n *\n * @since 0.0.3\n */\n fieldName?: string;\n\n /**\n * The MIME type of this file.\n * If not specified, the plugin will attempt to determine it automatically.\n *\n * @since 0.0.3\n */\n mimeType?: string;\n}\n\nexport interface uploadOption {\n /**\n * The local file path of the file to upload.\n * Can be a file:// URL or an absolute path.\n *\n * If you need to upload multiple files in a single multipart request, use `files`.\n *\n * @since 0.0.1\n */\n filePath?: string;\n\n /**\n * Multiple files to upload in a single request.\n *\n * When provided, uploads are sent as `multipart/form-data` with one part per file.\n * Use `fieldName` to control each part name (e.g. `images[]`).\n *\n * Note: `PUT` uploads (e.g. presigned S3 URLs) only support a single file.\n *\n * @since 0.0.3\n */\n files?: UploadFileOption[];\n\n /**\n * The server URL endpoint where the file should be uploaded.\n *\n * @since 0.0.1\n */\n serverUrl: string;\n\n /**\n * The title of the upload notification shown to the user.\n * Android only.\n *\n * @default 'Uploading'\n * @since 0.0.1\n */\n notificationTitle?: string;\n\n /**\n * HTTP headers to send with the upload request.\n * Useful for authentication tokens, content types, etc.\n *\n * @since 0.0.1\n * @example\n * ```typescript\n * headers: {\n * 'Authorization': 'Bearer token123',\n * 'X-Custom-Header': 'value'\n * }\n * ```\n */\n headers: {\n [key: string]: string;\n };\n\n /**\n * The HTTP method to use for the upload request.\n *\n * @default 'POST'\n * @since 0.0.1\n */\n method?: 'PUT' | 'POST';\n\n /**\n * The MIME type of the file being uploaded.\n * If not specified, the plugin will attempt to determine it automatically.\n *\n * @since 0.0.1\n * @example 'image/jpeg', 'application/pdf', 'video/mp4'\n */\n mimeType?: string;\n\n /**\n * Additional form parameters to send with the upload request.\n * These will be included as form data in multipart uploads.\n *\n * @since 0.0.1\n */\n parameters?: { [key: string]: string };\n\n /**\n * The maximum number of times to retry the upload if it fails.\n *\n * @since 0.0.1\n * @default 0\n */\n maxRetries?: number;\n\n /**\n * The type of upload to perform.\n * - 'binary': Uploads the file as raw binary data in the request body\n * - 'multipart': Uploads the file as multipart/form-data\n *\n * @default 'binary' when `method` is `'PUT'`, otherwise `'multipart'`\n * @since 0.0.2\n */\n uploadType?: 'binary' | 'multipart';\n\n /**\n * The form field name for the file when using multipart upload type.\n * Only used when uploadType is 'multipart'.\n *\n * For multi-file uploads via `files`, this is used as the default field name\n * when a file entry does not specify `fieldName`.\n *\n * @default 'file'\n * @since 0.0.2\n */\n fileField?: string;\n}\n\n/**\n * Event emitted during the upload lifecycle.\n *\n * @since 0.0.1\n */\nexport interface UploadEvent {\n /**\n * The current status of the upload.\n * - 'uploading': Upload is in progress\n * - 'completed': Upload finished successfully\n * - 'failed': Upload encountered an error\n *\n * @since 0.0.1\n */\n name: 'uploading' | 'completed' | 'failed';\n\n /**\n * Additional data about the upload event.\n *\n * @since 0.0.1\n */\n payload: {\n /**\n * Upload progress percentage from 0 to 100.\n * Only present during 'uploading' events.\n *\n * @since 0.0.1\n */\n percent?: number;\n\n /**\n * Error message if the upload failed.\n * Only present during 'failed' events.\n *\n * @since 0.0.1\n */\n error?: string;\n\n /**\n * HTTP status code returned by the server.\n * Present during 'completed' and 'failed' events.\n *\n * @since 0.0.1\n */\n statusCode?: number;\n };\n\n /**\n * Unique identifier for this upload task.\n *\n * @since 0.0.1\n */\n id: string;\n\n /**\n * Unique identifier for this specific event instance.\n * Only present on 'completed' and 'failed' events.\n * Used with acknowledgeEvent() to confirm receipt and remove the event from the plugin cache.\n * Progress ('uploading') events do not have an eventId and are not persisted.\n *\n * @since 0.0.2\n */\n eventId?: string;\n}\n\n/**\n * Capacitor Uploader Plugin for uploading files with background support and progress tracking.\n *\n * ### iOS setup\n *\n * On iOS the native layer uses a background `URLSession` with the identifier\n * `CapacitorUploaderBackgroundSession`. Many apps can upload without adding\n * `UIBackgroundModes`; add `fetch` when you need uploads to continue after the app\n * is suspended.\n *\n * App Store Connect rejects builds that declare `UIBackgroundModes` → `processing`\n * without `BGTaskSchedulerPermittedIdentifiers`. This plugin does not schedule\n * `BGTaskScheduler` work, so avoid `processing` unless another feature needs it.\n * If `processing` is present (for example from older setup guides), include\n * `CapacitorUploaderBackgroundSession` in `BGTaskSchedulerPermittedIdentifiers`\n * in your app's `Info.plist`.\n *\n * @example\n * ```xml\n * <key>UIBackgroundModes</key>\n * <array>\n * <string>fetch</string>\n * </array>\n * <key>BGTaskSchedulerPermittedIdentifiers</key>\n * <array>\n * <string>CapacitorUploaderBackgroundSession</string>\n * </array>\n * ```\n *\n * @since 0.0.1\n */\nexport interface UploaderPlugin {\n /**\n * Start uploading a file to a server.\n *\n * The upload will continue in the background even if the app is closed or backgrounded.\n * Listen to upload events to track progress, completion, or failure.\n *\n * @param options - Configuration for the upload\n * @returns Promise that resolves with the upload ID\n * @throws Error if the upload fails to start\n * @since 0.0.1\n * @example\n * ```typescript\n * const { id } = await Uploader.startUpload({\n * filePath: 'file:///path/to/file.jpg',\n * serverUrl: 'https://example.com/upload',\n * headers: {\n * 'Authorization': 'Bearer token'\n * },\n * method: 'POST',\n * uploadType: 'multipart',\n * fileField: 'photo'\n * });\n * console.log('Upload started with ID:', id);\n * ```\n *\n * @example\n * ```typescript\n * const { id } = await Uploader.startUpload({\n * serverUrl: 'https://api.example.com/upload',\n * method: 'POST',\n * uploadType: 'multipart',\n * files: [\n * { filePath: 'file:///...photo1.jpg', fieldName: 'images[]', mimeType: 'image/jpeg' },\n * { filePath: 'file:///...photo2.jpg', fieldName: 'images[]', mimeType: 'image/jpeg' },\n * ],\n * parameters: { albumId: '7' },\n * headers: { Authorization: 'Bearer token' },\n * });\n * console.log('Upload started with ID:', id);\n * ```\n */\n startUpload(options: uploadOption): Promise<{ id: string }>;\n\n /**\n * Cancel and remove an ongoing upload.\n *\n * This will stop the upload if it's in progress and clean up resources.\n *\n * @param options - Object containing the upload ID to remove\n * @returns Promise that resolves when the upload is removed\n * @throws Error if the upload ID is not found\n * @since 0.0.1\n * @example\n * ```typescript\n * await Uploader.removeUpload({ id: 'upload-123' });\n * ```\n */\n removeUpload(options: { id: string }): Promise<void>;\n\n /**\n * Listen for upload progress and status events.\n *\n * Events are fired for:\n * - Upload progress updates (with percent)\n * - Upload completion (with statusCode)\n * - Upload failure (with error and statusCode)\n *\n * @param eventName - Must be 'events'\n * @param listenerFunc - Callback function to handle upload events\n * @returns Promise that resolves with a listener handle for removal\n * @since 0.0.1\n * @example\n * ```typescript\n * const listener = await Uploader.addListener('events', (event) => {\n * if (event.name === 'uploading') {\n * console.log(`Upload ${event.id}: ${event.payload.percent}%`);\n * } else if (event.name === 'completed') {\n * console.log(`Upload ${event.id} completed`);\n * } else if (event.name === 'failed') {\n * console.error(`Upload ${event.id} failed:`, event.payload.error);\n * }\n * });\n *\n * // Remove listener when done\n * await listener.remove();\n * ```\n */\n addListener(eventName: 'events', listenerFunc: (state: UploadEvent) => void): Promise<PluginListenerHandle>;\n\n /**\n * Acknowledge receipt of an upload event and remove it from the plugin cache.\n *\n * Completed and failed events are stored in the plugin's persistent cache so they can be\n * re-delivered if the app is closed or backgrounded before the event is processed.\n * Call this method after successfully handling a 'completed' or 'failed' event to prevent\n * it from being re-broadcast the next time the plugin initialises.\n *\n * Progress ('uploading') events do not have an eventId and do not need to be acknowledged.\n *\n * @param options - Object containing the eventId to acknowledge\n * @returns Promise that resolves when the event has been removed from the cache\n * @since 0.0.2\n * @example\n * ```typescript\n * const listener = await Uploader.addListener('events', async (event) => {\n * if (event.name === 'completed' || event.name === 'failed') {\n * handleUploadResult(event);\n * if (event.eventId) {\n * await Uploader.acknowledgeEvent({ eventId: event.eventId });\n * }\n * }\n * });\n * ```\n */\n acknowledgeEvent(options: { eventId: string }): Promise<void>;\n\n /**\n * Get the native Capacitor plugin version.\n *\n * @returns Promise that resolves with the plugin version\n * @throws Error if getting the version fails\n * @since 0.0.1\n * @example\n * ```typescript\n * const { version } = await Uploader.getPluginVersion();\n * console.log('Plugin version:', version);\n * ```\n */\n getPluginVersion(): Promise<{ version: string }>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["import type { PluginListenerHandle } from '@capacitor/core';\n\n/**\n * Configuration options for uploading a file.\n *\n * @since 0.0.1\n */\nexport interface UploadFileOption {\n /**\n * The local file path of the file to upload.\n * Can be a file:// URL or an absolute path.\n *\n * @since 0.0.3\n */\n filePath: string;\n\n /**\n * The form field name for the file part when using multipart upload.\n *\n * If omitted, `uploadOption.fileField` is used (defaults to `'file'`).\n *\n * @since 0.0.3\n */\n fieldName?: string;\n\n /**\n * The MIME type of this file.\n * If not specified, the plugin will attempt to determine it automatically.\n *\n * @since 0.0.3\n */\n mimeType?: string;\n}\n\n/**\n * Options for starting a single-file multipart upload.\n *\n * @since 8.3.2\n */\nexport interface UploadMultipartOptions {\n /**\n * The server URL endpoint where the multipart request should be sent.\n *\n * @since 8.3.2\n */\n url: string;\n\n /**\n * The local file path of the file to upload.\n * Can be a file:// URL or an absolute path.\n *\n * @since 8.3.2\n */\n filePath: string;\n\n /**\n * The form field name for the uploaded file part.\n *\n * @since 8.3.2\n */\n fieldName: string;\n\n /**\n * Additional form fields to include in the multipart request.\n *\n * @since 8.3.2\n */\n fields?: { [key: string]: string };\n\n /**\n * HTTP headers to send with the upload request.\n *\n * @since 8.3.2\n */\n headers?: { [key: string]: string };\n}\n\nexport interface uploadOption {\n /**\n * The local file path of the file to upload.\n * Can be a file:// URL or an absolute path.\n *\n * If you need to upload multiple files in a single multipart request, use `files`.\n *\n * @since 0.0.1\n */\n filePath?: string;\n\n /**\n * Multiple files to upload in a single request.\n *\n * When provided, uploads are sent as `multipart/form-data` with one part per file.\n * Use `fieldName` to control each part name (e.g. `images[]`).\n *\n * Note: `PUT` uploads (e.g. presigned S3 URLs) only support a single file.\n *\n * @since 0.0.3\n */\n files?: UploadFileOption[];\n\n /**\n * The server URL endpoint where the file should be uploaded.\n *\n * @since 0.0.1\n */\n serverUrl: string;\n\n /**\n * The title of the upload notification shown to the user.\n * Android only.\n *\n * @default 'Uploading'\n * @since 0.0.1\n */\n notificationTitle?: string;\n\n /**\n * HTTP headers to send with the upload request.\n * Useful for authentication tokens, content types, etc.\n *\n * @since 0.0.1\n * @example\n * ```typescript\n * headers: {\n * 'Authorization': 'Bearer token123',\n * 'X-Custom-Header': 'value'\n * }\n * ```\n */\n headers: {\n [key: string]: string;\n };\n\n /**\n * The HTTP method to use for the upload request.\n *\n * @default 'POST'\n * @since 0.0.1\n */\n method?: 'PUT' | 'POST';\n\n /**\n * The MIME type of the file being uploaded.\n * If not specified, the plugin will attempt to determine it automatically.\n *\n * @since 0.0.1\n * @example 'image/jpeg', 'application/pdf', 'video/mp4'\n */\n mimeType?: string;\n\n /**\n * Additional form parameters to send with the upload request.\n * These will be included as form data in multipart uploads.\n *\n * @since 0.0.1\n */\n parameters?: { [key: string]: string };\n\n /**\n * The maximum number of times to retry the upload if it fails.\n *\n * @since 0.0.1\n * @default 0\n */\n maxRetries?: number;\n\n /**\n * The type of upload to perform.\n * - 'binary': Uploads the file as raw binary data in the request body\n * - 'multipart': Uploads the file as multipart/form-data\n *\n * @default 'binary' when `method` is `'PUT'`, otherwise `'multipart'`\n * @since 0.0.2\n */\n uploadType?: 'binary' | 'multipart';\n\n /**\n * The form field name for the file when using multipart upload type.\n * Only used when uploadType is 'multipart'.\n *\n * For multi-file uploads via `files`, this is used as the default field name\n * when a file entry does not specify `fieldName`.\n *\n * @default 'file'\n * @since 0.0.2\n */\n fileField?: string;\n}\n\n/**\n * Event emitted during the upload lifecycle.\n *\n * @since 0.0.1\n */\nexport interface UploadEvent {\n /**\n * The current status of the upload.\n * - 'uploading': Upload is in progress\n * - 'completed': Upload finished successfully\n * - 'failed': Upload encountered an error\n *\n * @since 0.0.1\n */\n name: 'uploading' | 'completed' | 'failed';\n\n /**\n * Additional data about the upload event.\n *\n * @since 0.0.1\n */\n payload: {\n /**\n * Upload progress percentage from 0 to 100.\n * Only present during 'uploading' events.\n *\n * @since 0.0.1\n */\n percent?: number;\n\n /**\n * Error message if the upload failed.\n * Only present during 'failed' events.\n *\n * @since 0.0.1\n */\n error?: string;\n\n /**\n * HTTP status code returned by the server.\n * Present during 'completed' and 'failed' events.\n *\n * @since 0.0.1\n */\n statusCode?: number;\n };\n\n /**\n * Unique identifier for this upload task.\n *\n * @since 0.0.1\n */\n id: string;\n\n /**\n * Unique identifier for this specific event instance.\n * Only present on 'completed' and 'failed' events.\n * Used with acknowledgeEvent() to confirm receipt and remove the event from the plugin cache.\n * Progress ('uploading') events do not have an eventId and are not persisted.\n *\n * @since 0.0.2\n */\n eventId?: string;\n}\n\n/**\n * Capacitor Uploader Plugin for uploading files with background support and progress tracking.\n *\n * ### iOS setup\n *\n * On iOS the native layer uses a background `URLSession` with the identifier\n * `CapacitorUploaderBackgroundSession`. Many apps can upload without adding\n * `UIBackgroundModes`; add `fetch` when you need uploads to continue after the app\n * is suspended.\n *\n * App Store Connect rejects builds that declare `UIBackgroundModes` → `processing`\n * without `BGTaskSchedulerPermittedIdentifiers`. This plugin does not schedule\n * `BGTaskScheduler` work, so avoid `processing` unless another feature needs it.\n * If `processing` is present (for example from older setup guides), include\n * `CapacitorUploaderBackgroundSession` in `BGTaskSchedulerPermittedIdentifiers`\n * in your app's `Info.plist`.\n *\n * @example\n * ```xml\n * <key>UIBackgroundModes</key>\n * <array>\n * <string>fetch</string>\n * </array>\n * <key>BGTaskSchedulerPermittedIdentifiers</key>\n * <array>\n * <string>CapacitorUploaderBackgroundSession</string>\n * </array>\n * ```\n *\n * @since 0.0.1\n */\nexport interface UploaderPlugin {\n /**\n * Start uploading a file to a server.\n *\n * The upload will continue in the background even if the app is closed or backgrounded.\n * Listen to upload events to track progress, completion, or failure.\n *\n * @param options - Configuration for the upload\n * @returns Promise that resolves with the upload ID\n * @throws Error if the upload fails to start\n * @since 0.0.1\n * @example\n * ```typescript\n * const { id } = await Uploader.startUpload({\n * filePath: 'file:///path/to/file.jpg',\n * serverUrl: 'https://example.com/upload',\n * headers: {\n * 'Authorization': 'Bearer token'\n * },\n * method: 'POST',\n * uploadType: 'multipart',\n * fileField: 'photo'\n * });\n * console.log('Upload started with ID:', id);\n * ```\n *\n * @example\n * ```typescript\n * const { id } = await Uploader.startUpload({\n * serverUrl: 'https://api.example.com/upload',\n * method: 'POST',\n * uploadType: 'multipart',\n * files: [\n * { filePath: 'file:///...photo1.jpg', fieldName: 'images[]', mimeType: 'image/jpeg' },\n * { filePath: 'file:///...photo2.jpg', fieldName: 'images[]', mimeType: 'image/jpeg' },\n * ],\n * parameters: { albumId: '7' },\n * headers: { Authorization: 'Bearer token' },\n * });\n * console.log('Upload started with ID:', id);\n * ```\n */\n startUpload(options: uploadOption): Promise<{ id: string }>;\n\n /**\n * Start uploading a single file as multipart/form-data.\n *\n * This is a convenience API for backends that expect a named file field and\n * additional form fields. Existing `startUpload` binary uploads are unchanged.\n *\n * @param options - Configuration for the multipart upload\n * @returns Promise that resolves with the upload ID\n * @throws Error if the upload fails to start\n * @since 8.3.2\n * @example\n * ```typescript\n * const { id } = await Uploader.uploadMultipart({\n * url: 'https://example.com/upload',\n * filePath: 'file:///path/to/file.jpg',\n * fieldName: 'photo',\n * fields: { albumId: '7' },\n * headers: { Authorization: 'Bearer token' },\n * });\n * console.log('Upload started with ID:', id);\n * ```\n */\n uploadMultipart(options: UploadMultipartOptions): Promise<{ id: string }>;\n\n /**\n * Cancel and remove an ongoing upload.\n *\n * This will stop the upload if it's in progress and clean up resources.\n *\n * @param options - Object containing the upload ID to remove\n * @returns Promise that resolves when the upload is removed\n * @throws Error if the upload ID is not found\n * @since 0.0.1\n * @example\n * ```typescript\n * await Uploader.removeUpload({ id: 'upload-123' });\n * ```\n */\n removeUpload(options: { id: string }): Promise<void>;\n\n /**\n * Listen for upload progress and status events.\n *\n * Events are fired for:\n * - Upload progress updates (with percent)\n * - Upload completion (with statusCode)\n * - Upload failure (with error and statusCode)\n *\n * @param eventName - Must be 'events'\n * @param listenerFunc - Callback function to handle upload events\n * @returns Promise that resolves with a listener handle for removal\n * @since 0.0.1\n * @example\n * ```typescript\n * const listener = await Uploader.addListener('events', (event) => {\n * if (event.name === 'uploading') {\n * console.log(`Upload ${event.id}: ${event.payload.percent}%`);\n * } else if (event.name === 'completed') {\n * console.log(`Upload ${event.id} completed`);\n * } else if (event.name === 'failed') {\n * console.error(`Upload ${event.id} failed:`, event.payload.error);\n * }\n * });\n *\n * // Remove listener when done\n * await listener.remove();\n * ```\n */\n addListener(eventName: 'events', listenerFunc: (state: UploadEvent) => void): Promise<PluginListenerHandle>;\n\n /**\n * Acknowledge receipt of an upload event and remove it from the plugin cache.\n *\n * Completed and failed events are stored in the plugin's persistent cache so they can be\n * re-delivered if the app is closed or backgrounded before the event is processed.\n * Call this method after successfully handling a 'completed' or 'failed' event to prevent\n * it from being re-broadcast the next time the plugin initialises.\n *\n * Progress ('uploading') events do not have an eventId and do not need to be acknowledged.\n *\n * @param options - Object containing the eventId to acknowledge\n * @returns Promise that resolves when the event has been removed from the cache\n * @since 0.0.2\n * @example\n * ```typescript\n * const listener = await Uploader.addListener('events', async (event) => {\n * if (event.name === 'completed' || event.name === 'failed') {\n * handleUploadResult(event);\n * if (event.eventId) {\n * await Uploader.acknowledgeEvent({ eventId: event.eventId });\n * }\n * }\n * });\n * ```\n */\n acknowledgeEvent(options: { eventId: string }): Promise<void>;\n\n /**\n * Get the native Capacitor plugin version.\n *\n * @returns Promise that resolves with the plugin version\n * @throws Error if getting the version fails\n * @since 0.0.1\n * @example\n * ```typescript\n * const { version } = await Uploader.getPluginVersion();\n * console.log('Plugin version:', version);\n * ```\n */\n getPluginVersion(): Promise<{ version: string }>;\n}\n"]}
|
package/dist/esm/web.d.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { WebPlugin } from '@capacitor/core';
|
|
2
|
-
import type { UploaderPlugin, uploadOption } from './definitions';
|
|
2
|
+
import type { UploadMultipartOptions, UploaderPlugin, uploadOption } from './definitions';
|
|
3
3
|
export declare class UploaderWeb extends WebPlugin implements UploaderPlugin {
|
|
4
4
|
private uploads;
|
|
5
5
|
startUpload(options: uploadOption): Promise<{
|
|
6
6
|
id: string;
|
|
7
7
|
}>;
|
|
8
|
+
uploadMultipart(options: UploadMultipartOptions): Promise<{
|
|
9
|
+
id: string;
|
|
10
|
+
}>;
|
|
8
11
|
removeUpload(options: {
|
|
9
12
|
id: string;
|
|
10
13
|
}): Promise<void>;
|
package/dist/esm/web.js
CHANGED
|
@@ -15,6 +15,18 @@ export class UploaderWeb extends WebPlugin {
|
|
|
15
15
|
this.doUpload(id, options);
|
|
16
16
|
return { id };
|
|
17
17
|
}
|
|
18
|
+
async uploadMultipart(options) {
|
|
19
|
+
var _a, _b;
|
|
20
|
+
return this.startUpload({
|
|
21
|
+
filePath: options.filePath,
|
|
22
|
+
serverUrl: options.url,
|
|
23
|
+
headers: (_a = options.headers) !== null && _a !== void 0 ? _a : {},
|
|
24
|
+
method: 'POST',
|
|
25
|
+
uploadType: 'multipart',
|
|
26
|
+
fileField: options.fieldName,
|
|
27
|
+
parameters: (_b = options.fields) !== null && _b !== void 0 ? _b : {},
|
|
28
|
+
});
|
|
29
|
+
}
|
|
18
30
|
async removeUpload(options) {
|
|
19
31
|
console.log('removeUpload', options);
|
|
20
32
|
const upload = this.uploads.get(options.id);
|
package/dist/esm/web.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"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","sourcesContent":["import { WebPlugin } from '@capacitor/core';\nimport { openDB } from 'idb';\n\nimport { PathHelper } from './PathHelper';\nimport type { UploadFileOption, UploaderPlugin, uploadOption } from './definitions';\n\nexport class UploaderWeb extends WebPlugin implements UploaderPlugin {\n private uploads: Map<string, { controller: AbortController; retries: number }> = new Map();\n\n async startUpload(options: uploadOption): Promise<{ id: string }> {\n console.log('startUpload', options);\n\n const id = Math.random().toString(36).substring(2, 15);\n const controller = new AbortController();\n const maxRetries = options.maxRetries || 3;\n this.uploads.set(id, { controller, retries: maxRetries });\n\n this.doUpload(id, options);\n\n return { id };\n }\n\n async removeUpload(options: { id: string }): Promise<void> {\n console.log('removeUpload', options);\n const upload = this.uploads.get(options.id);\n if (upload) {\n upload.controller.abort();\n this.uploads.delete(options.id);\n this.notifyListeners('events', {\n name: 'cancelled',\n id: options.id,\n payload: {},\n });\n }\n }\n\n private async doUpload(id: string, options: uploadOption) {\n const { serverUrl, headers = {}, method = 'POST', parameters = {} } = options;\n const upload = this.uploads.get(id);\n\n if (!upload) return;\n\n try {\n const files = this.normalizeFiles(options);\n if (files.length === 0) throw new Error('Missing required parameter: filePath or files');\n\n const resolvedMethod = method.toUpperCase();\n const uploadType = options.uploadType ?? (resolvedMethod === 'PUT' ? 'binary' : 'multipart');\n\n let body: BodyInit;\n if (resolvedMethod === 'PUT' || uploadType === 'binary') {\n if (files.length !== 1) throw new Error('Binary uploads only support a single file');\n const file = await this.getFileFromPath(files[0].filePath);\n if (!file) throw new Error('File not found');\n body = file;\n } else {\n const formData = new FormData();\n\n for (const fileOption of files) {\n const file = await this.getFileFromPath(fileOption.filePath);\n if (!file) throw new Error('File not found');\n const fieldName = fileOption.fieldName ?? options.fileField ?? 'file';\n formData.append(fieldName, file);\n }\n\n for (const [key, value] of Object.entries(parameters)) {\n formData.append(key, value);\n }\n\n body = formData;\n }\n\n const response = await fetch(serverUrl, {\n method: resolvedMethod,\n headers,\n body,\n signal: upload.controller.signal,\n });\n\n if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);\n\n this.notifyListeners('events', {\n name: 'completed',\n id,\n payload: { statusCode: response.status },\n });\n\n this.uploads.delete(id);\n } catch (error) {\n if ((error as Error).name === 'AbortError') return;\n\n if (upload.retries > 0) {\n upload.retries--;\n console.log(`Retrying upload (retries left: ${upload.retries})`);\n setTimeout(() => this.doUpload(id, options), 1000);\n } else {\n this.notifyListeners('events', {\n name: 'failed',\n id,\n payload: { error: (error as Error).message },\n });\n this.uploads.delete(id);\n }\n }\n }\n\n private normalizeFiles(options: uploadOption): UploadFileOption[] {\n if (options.files && options.files.length > 0) return options.files;\n if (options.filePath) {\n return [\n {\n filePath: options.filePath,\n fieldName: options.fileField,\n mimeType: options.mimeType,\n },\n ];\n }\n return [];\n }\n\n private async getFileFromPath(filePath: string): Promise<File | null> {\n // Check if the path is an IndexedDB path\n if (PathHelper.isIndexedDBPath(filePath)) {\n return this.getFileFromIndexedDB(filePath);\n }\n\n // Otherwise, treat it as a file path from the system\n return this.getFileFromSystem(filePath);\n }\n\n // Retrieve the file from IndexedDB\n private async getFileFromIndexedDB(filePath: string): Promise<File | null> {\n // Parse the path to get the database, store name, and key\n const { database, storeName, key } = PathHelper.parseIndexedDBPath(filePath);\n\n try {\n // Open the IndexedDB database and access the object store\n const db = await openDB(database, 1, {\n upgrade(db) {\n if (!db.objectStoreNames.contains(storeName)) {\n db.createObjectStore(storeName);\n }\n },\n });\n\n // Get the blob from the store\n const blob = await db.get(storeName, key);\n if (!blob) {\n console.error(`File with key \"${key}\" not found in store \"${storeName}\" in database \"${database}\"`);\n return null;\n }\n\n // Convert the Blob to a File object\n return new File([blob], key, { type: blob.type });\n } catch (error) {\n console.error('Error retrieving file from IndexedDB:', error);\n return null;\n }\n }\n\n // Retrieve the file from the system (local file)\n private async getFileFromSystem(filePath: string): Promise<File | null> {\n try {\n // This is a simplified version. In a real-world scenario,\n // you might need to handle different types of paths or use a file system API.\n const response = await fetch(filePath);\n const blob = await response.blob();\n return new File([blob], filePath.split('/').pop() || 'file', {\n type: blob.type,\n });\n } catch (error) {\n console.error('Error getting file from system:', error);\n return null;\n }\n }\n\n async acknowledgeEvent(_options: { eventId: string }): Promise<void> {\n // Web uploads run in-process; events are not persisted for replay.\n }\n\n async getPluginVersion(): Promise<{ version: string }> {\n return { version: 'web' };\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"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","sourcesContent":["import { WebPlugin } from '@capacitor/core';\nimport { openDB } from 'idb';\n\nimport { PathHelper } from './PathHelper';\nimport type { UploadFileOption, UploadMultipartOptions, UploaderPlugin, uploadOption } from './definitions';\n\nexport class UploaderWeb extends WebPlugin implements UploaderPlugin {\n private uploads: Map<string, { controller: AbortController; retries: number }> = new Map();\n\n async startUpload(options: uploadOption): Promise<{ id: string }> {\n console.log('startUpload', options);\n\n const id = Math.random().toString(36).substring(2, 15);\n const controller = new AbortController();\n const maxRetries = options.maxRetries || 3;\n this.uploads.set(id, { controller, retries: maxRetries });\n\n this.doUpload(id, options);\n\n return { id };\n }\n\n async uploadMultipart(options: UploadMultipartOptions): Promise<{ id: string }> {\n return this.startUpload({\n filePath: options.filePath,\n serverUrl: options.url,\n headers: options.headers ?? {},\n method: 'POST',\n uploadType: 'multipart',\n fileField: options.fieldName,\n parameters: options.fields ?? {},\n });\n }\n\n async removeUpload(options: { id: string }): Promise<void> {\n console.log('removeUpload', options);\n const upload = this.uploads.get(options.id);\n if (upload) {\n upload.controller.abort();\n this.uploads.delete(options.id);\n this.notifyListeners('events', {\n name: 'cancelled',\n id: options.id,\n payload: {},\n });\n }\n }\n\n private async doUpload(id: string, options: uploadOption) {\n const { serverUrl, headers = {}, method = 'POST', parameters = {} } = options;\n const upload = this.uploads.get(id);\n\n if (!upload) return;\n\n try {\n const files = this.normalizeFiles(options);\n if (files.length === 0) throw new Error('Missing required parameter: filePath or files');\n\n const resolvedMethod = method.toUpperCase();\n const uploadType = options.uploadType ?? (resolvedMethod === 'PUT' ? 'binary' : 'multipart');\n\n let body: BodyInit;\n if (resolvedMethod === 'PUT' || uploadType === 'binary') {\n if (files.length !== 1) throw new Error('Binary uploads only support a single file');\n const file = await this.getFileFromPath(files[0].filePath);\n if (!file) throw new Error('File not found');\n body = file;\n } else {\n const formData = new FormData();\n\n for (const fileOption of files) {\n const file = await this.getFileFromPath(fileOption.filePath);\n if (!file) throw new Error('File not found');\n const fieldName = fileOption.fieldName ?? options.fileField ?? 'file';\n formData.append(fieldName, file);\n }\n\n for (const [key, value] of Object.entries(parameters)) {\n formData.append(key, value);\n }\n\n body = formData;\n }\n\n const response = await fetch(serverUrl, {\n method: resolvedMethod,\n headers,\n body,\n signal: upload.controller.signal,\n });\n\n if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);\n\n this.notifyListeners('events', {\n name: 'completed',\n id,\n payload: { statusCode: response.status },\n });\n\n this.uploads.delete(id);\n } catch (error) {\n if ((error as Error).name === 'AbortError') return;\n\n if (upload.retries > 0) {\n upload.retries--;\n console.log(`Retrying upload (retries left: ${upload.retries})`);\n setTimeout(() => this.doUpload(id, options), 1000);\n } else {\n this.notifyListeners('events', {\n name: 'failed',\n id,\n payload: { error: (error as Error).message },\n });\n this.uploads.delete(id);\n }\n }\n }\n\n private normalizeFiles(options: uploadOption): UploadFileOption[] {\n if (options.files && options.files.length > 0) return options.files;\n if (options.filePath) {\n return [\n {\n filePath: options.filePath,\n fieldName: options.fileField,\n mimeType: options.mimeType,\n },\n ];\n }\n return [];\n }\n\n private async getFileFromPath(filePath: string): Promise<File | null> {\n // Check if the path is an IndexedDB path\n if (PathHelper.isIndexedDBPath(filePath)) {\n return this.getFileFromIndexedDB(filePath);\n }\n\n // Otherwise, treat it as a file path from the system\n return this.getFileFromSystem(filePath);\n }\n\n // Retrieve the file from IndexedDB\n private async getFileFromIndexedDB(filePath: string): Promise<File | null> {\n // Parse the path to get the database, store name, and key\n const { database, storeName, key } = PathHelper.parseIndexedDBPath(filePath);\n\n try {\n // Open the IndexedDB database and access the object store\n const db = await openDB(database, 1, {\n upgrade(db) {\n if (!db.objectStoreNames.contains(storeName)) {\n db.createObjectStore(storeName);\n }\n },\n });\n\n // Get the blob from the store\n const blob = await db.get(storeName, key);\n if (!blob) {\n console.error(`File with key \"${key}\" not found in store \"${storeName}\" in database \"${database}\"`);\n return null;\n }\n\n // Convert the Blob to a File object\n return new File([blob], key, { type: blob.type });\n } catch (error) {\n console.error('Error retrieving file from IndexedDB:', error);\n return null;\n }\n }\n\n // Retrieve the file from the system (local file)\n private async getFileFromSystem(filePath: string): Promise<File | null> {\n try {\n // This is a simplified version. In a real-world scenario,\n // you might need to handle different types of paths or use a file system API.\n const response = await fetch(filePath);\n const blob = await response.blob();\n return new File([blob], filePath.split('/').pop() || 'file', {\n type: blob.type,\n });\n } catch (error) {\n console.error('Error getting file from system:', error);\n return null;\n }\n }\n\n async acknowledgeEvent(_options: { eventId: string }): Promise<void> {\n // Web uploads run in-process; events are not persisted for replay.\n }\n\n async getPluginVersion(): Promise<{ version: string }> {\n return { version: 'web' };\n }\n}\n"]}
|
package/dist/plugin.cjs.js
CHANGED
|
@@ -42,6 +42,18 @@ class UploaderWeb extends core.WebPlugin {
|
|
|
42
42
|
this.doUpload(id, options);
|
|
43
43
|
return { id };
|
|
44
44
|
}
|
|
45
|
+
async uploadMultipart(options) {
|
|
46
|
+
var _a, _b;
|
|
47
|
+
return this.startUpload({
|
|
48
|
+
filePath: options.filePath,
|
|
49
|
+
serverUrl: options.url,
|
|
50
|
+
headers: (_a = options.headers) !== null && _a !== void 0 ? _a : {},
|
|
51
|
+
method: 'POST',
|
|
52
|
+
uploadType: 'multipart',
|
|
53
|
+
fileField: options.fieldName,
|
|
54
|
+
parameters: (_b = options.fields) !== null && _b !== void 0 ? _b : {},
|
|
55
|
+
});
|
|
56
|
+
}
|
|
45
57
|
async removeUpload(options) {
|
|
46
58
|
console.log('removeUpload', options);
|
|
47
59
|
const upload = this.uploads.get(options.id);
|
package/dist/plugin.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/PathHelper.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst Uploader = registerPlugin('Uploader', {\n web: () => import('./web').then((m) => new m.UploaderWeb()),\n});\nexport * from './definitions';\nexport { Uploader };\n//# sourceMappingURL=index.js.map","export class PathHelper {\n // Check if the path follows the idb://[databaseName]/[storeName]/[key] format\n static isIndexedDBPath(path) {\n const regex = /^idb:\\/\\/([^/]+)\\/([^/]+)\\/(.+)$/;\n return regex.test(path);\n }\n // Parse the path to extract database, storeName, and key\n static parseIndexedDBPath(path) {\n const regex = /^idb:\\/\\/([^/]+)\\/([^/]+)\\/(.+)$/;\n const match = path.match(regex);\n if (!match) {\n throw new Error('Invalid IndexedDB path format');\n }\n return {\n database: match[1],\n storeName: match[2],\n key: match[3],\n };\n }\n}\n//# sourceMappingURL=PathHelper.js.map","import { WebPlugin } from '@capacitor/core';\nimport { openDB } from 'idb';\nimport { PathHelper } from './PathHelper';\nexport class UploaderWeb extends WebPlugin {\n constructor() {\n super(...arguments);\n this.uploads = new Map();\n }\n async startUpload(options) {\n console.log('startUpload', options);\n const id = Math.random().toString(36).substring(2, 15);\n const controller = new AbortController();\n const maxRetries = options.maxRetries || 3;\n this.uploads.set(id, { controller, retries: maxRetries });\n this.doUpload(id, options);\n return { id };\n }\n async removeUpload(options) {\n console.log('removeUpload', options);\n const upload = this.uploads.get(options.id);\n if (upload) {\n upload.controller.abort();\n this.uploads.delete(options.id);\n this.notifyListeners('events', {\n name: 'cancelled',\n id: options.id,\n payload: {},\n });\n }\n }\n async doUpload(id, options) {\n var _a, _b, _c;\n const { serverUrl, headers = {}, method = 'POST', parameters = {} } = options;\n const upload = this.uploads.get(id);\n if (!upload)\n return;\n try {\n const files = this.normalizeFiles(options);\n if (files.length === 0)\n throw new Error('Missing required parameter: filePath or files');\n const resolvedMethod = method.toUpperCase();\n const uploadType = (_a = options.uploadType) !== null && _a !== void 0 ? _a : (resolvedMethod === 'PUT' ? 'binary' : 'multipart');\n let body;\n if (resolvedMethod === 'PUT' || uploadType === 'binary') {\n if (files.length !== 1)\n throw new Error('Binary uploads only support a single file');\n const file = await this.getFileFromPath(files[0].filePath);\n if (!file)\n throw new Error('File not found');\n body = file;\n }\n else {\n const formData = new FormData();\n for (const fileOption of files) {\n const file = await this.getFileFromPath(fileOption.filePath);\n if (!file)\n throw new Error('File not found');\n const fieldName = (_c = (_b = fileOption.fieldName) !== null && _b !== void 0 ? _b : options.fileField) !== null && _c !== void 0 ? _c : 'file';\n formData.append(fieldName, file);\n }\n for (const [key, value] of Object.entries(parameters)) {\n formData.append(key, value);\n }\n body = formData;\n }\n const response = await fetch(serverUrl, {\n method: resolvedMethod,\n headers,\n body,\n signal: upload.controller.signal,\n });\n if (!response.ok)\n throw new Error(`HTTP error! status: ${response.status}`);\n this.notifyListeners('events', {\n name: 'completed',\n id,\n payload: { statusCode: response.status },\n });\n this.uploads.delete(id);\n }\n catch (error) {\n if (error.name === 'AbortError')\n return;\n if (upload.retries > 0) {\n upload.retries--;\n console.log(`Retrying upload (retries left: ${upload.retries})`);\n setTimeout(() => this.doUpload(id, options), 1000);\n }\n else {\n this.notifyListeners('events', {\n name: 'failed',\n id,\n payload: { error: error.message },\n });\n this.uploads.delete(id);\n }\n }\n }\n normalizeFiles(options) {\n if (options.files && options.files.length > 0)\n return options.files;\n if (options.filePath) {\n return [\n {\n filePath: options.filePath,\n fieldName: options.fileField,\n mimeType: options.mimeType,\n },\n ];\n }\n return [];\n }\n async getFileFromPath(filePath) {\n // Check if the path is an IndexedDB path\n if (PathHelper.isIndexedDBPath(filePath)) {\n return this.getFileFromIndexedDB(filePath);\n }\n // Otherwise, treat it as a file path from the system\n return this.getFileFromSystem(filePath);\n }\n // Retrieve the file from IndexedDB\n async getFileFromIndexedDB(filePath) {\n // Parse the path to get the database, store name, and key\n const { database, storeName, key } = PathHelper.parseIndexedDBPath(filePath);\n try {\n // Open the IndexedDB database and access the object store\n const db = await openDB(database, 1, {\n upgrade(db) {\n if (!db.objectStoreNames.contains(storeName)) {\n db.createObjectStore(storeName);\n }\n },\n });\n // Get the blob from the store\n const blob = await db.get(storeName, key);\n if (!blob) {\n console.error(`File with key \"${key}\" not found in store \"${storeName}\" in database \"${database}\"`);\n return null;\n }\n // Convert the Blob to a File object\n return new File([blob], key, { type: blob.type });\n }\n catch (error) {\n console.error('Error retrieving file from IndexedDB:', error);\n return null;\n }\n }\n // Retrieve the file from the system (local file)\n async getFileFromSystem(filePath) {\n try {\n // This is a simplified version. In a real-world scenario,\n // you might need to handle different types of paths or use a file system API.\n const response = await fetch(filePath);\n const blob = await response.blob();\n return new File([blob], filePath.split('/').pop() || 'file', {\n type: blob.type,\n });\n }\n catch (error) {\n console.error('Error getting file from system:', error);\n return null;\n }\n }\n async acknowledgeEvent(_options) {\n // Web uploads run in-process; events are not persisted for replay.\n }\n async getPluginVersion() {\n return { version: 'web' };\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin","openDB"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/PathHelper.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst Uploader = registerPlugin('Uploader', {\n web: () => import('./web').then((m) => new m.UploaderWeb()),\n});\nexport * from './definitions';\nexport { Uploader };\n//# sourceMappingURL=index.js.map","export class PathHelper {\n // Check if the path follows the idb://[databaseName]/[storeName]/[key] format\n static isIndexedDBPath(path) {\n const regex = /^idb:\\/\\/([^/]+)\\/([^/]+)\\/(.+)$/;\n return regex.test(path);\n }\n // Parse the path to extract database, storeName, and key\n static parseIndexedDBPath(path) {\n const regex = /^idb:\\/\\/([^/]+)\\/([^/]+)\\/(.+)$/;\n const match = path.match(regex);\n if (!match) {\n throw new Error('Invalid IndexedDB path format');\n }\n return {\n database: match[1],\n storeName: match[2],\n key: match[3],\n };\n }\n}\n//# sourceMappingURL=PathHelper.js.map","import { WebPlugin } from '@capacitor/core';\nimport { openDB } from 'idb';\nimport { PathHelper } from './PathHelper';\nexport class UploaderWeb extends WebPlugin {\n constructor() {\n super(...arguments);\n this.uploads = new Map();\n }\n async startUpload(options) {\n console.log('startUpload', options);\n const id = Math.random().toString(36).substring(2, 15);\n const controller = new AbortController();\n const maxRetries = options.maxRetries || 3;\n this.uploads.set(id, { controller, retries: maxRetries });\n this.doUpload(id, options);\n return { id };\n }\n async uploadMultipart(options) {\n var _a, _b;\n return this.startUpload({\n filePath: options.filePath,\n serverUrl: options.url,\n headers: (_a = options.headers) !== null && _a !== void 0 ? _a : {},\n method: 'POST',\n uploadType: 'multipart',\n fileField: options.fieldName,\n parameters: (_b = options.fields) !== null && _b !== void 0 ? _b : {},\n });\n }\n async removeUpload(options) {\n console.log('removeUpload', options);\n const upload = this.uploads.get(options.id);\n if (upload) {\n upload.controller.abort();\n this.uploads.delete(options.id);\n this.notifyListeners('events', {\n name: 'cancelled',\n id: options.id,\n payload: {},\n });\n }\n }\n async doUpload(id, options) {\n var _a, _b, _c;\n const { serverUrl, headers = {}, method = 'POST', parameters = {} } = options;\n const upload = this.uploads.get(id);\n if (!upload)\n return;\n try {\n const files = this.normalizeFiles(options);\n if (files.length === 0)\n throw new Error('Missing required parameter: filePath or files');\n const resolvedMethod = method.toUpperCase();\n const uploadType = (_a = options.uploadType) !== null && _a !== void 0 ? _a : (resolvedMethod === 'PUT' ? 'binary' : 'multipart');\n let body;\n if (resolvedMethod === 'PUT' || uploadType === 'binary') {\n if (files.length !== 1)\n throw new Error('Binary uploads only support a single file');\n const file = await this.getFileFromPath(files[0].filePath);\n if (!file)\n throw new Error('File not found');\n body = file;\n }\n else {\n const formData = new FormData();\n for (const fileOption of files) {\n const file = await this.getFileFromPath(fileOption.filePath);\n if (!file)\n throw new Error('File not found');\n const fieldName = (_c = (_b = fileOption.fieldName) !== null && _b !== void 0 ? _b : options.fileField) !== null && _c !== void 0 ? _c : 'file';\n formData.append(fieldName, file);\n }\n for (const [key, value] of Object.entries(parameters)) {\n formData.append(key, value);\n }\n body = formData;\n }\n const response = await fetch(serverUrl, {\n method: resolvedMethod,\n headers,\n body,\n signal: upload.controller.signal,\n });\n if (!response.ok)\n throw new Error(`HTTP error! status: ${response.status}`);\n this.notifyListeners('events', {\n name: 'completed',\n id,\n payload: { statusCode: response.status },\n });\n this.uploads.delete(id);\n }\n catch (error) {\n if (error.name === 'AbortError')\n return;\n if (upload.retries > 0) {\n upload.retries--;\n console.log(`Retrying upload (retries left: ${upload.retries})`);\n setTimeout(() => this.doUpload(id, options), 1000);\n }\n else {\n this.notifyListeners('events', {\n name: 'failed',\n id,\n payload: { error: error.message },\n });\n this.uploads.delete(id);\n }\n }\n }\n normalizeFiles(options) {\n if (options.files && options.files.length > 0)\n return options.files;\n if (options.filePath) {\n return [\n {\n filePath: options.filePath,\n fieldName: options.fileField,\n mimeType: options.mimeType,\n },\n ];\n }\n return [];\n }\n async getFileFromPath(filePath) {\n // Check if the path is an IndexedDB path\n if (PathHelper.isIndexedDBPath(filePath)) {\n return this.getFileFromIndexedDB(filePath);\n }\n // Otherwise, treat it as a file path from the system\n return this.getFileFromSystem(filePath);\n }\n // Retrieve the file from IndexedDB\n async getFileFromIndexedDB(filePath) {\n // Parse the path to get the database, store name, and key\n const { database, storeName, key } = PathHelper.parseIndexedDBPath(filePath);\n try {\n // Open the IndexedDB database and access the object store\n const db = await openDB(database, 1, {\n upgrade(db) {\n if (!db.objectStoreNames.contains(storeName)) {\n db.createObjectStore(storeName);\n }\n },\n });\n // Get the blob from the store\n const blob = await db.get(storeName, key);\n if (!blob) {\n console.error(`File with key \"${key}\" not found in store \"${storeName}\" in database \"${database}\"`);\n return null;\n }\n // Convert the Blob to a File object\n return new File([blob], key, { type: blob.type });\n }\n catch (error) {\n console.error('Error retrieving file from IndexedDB:', error);\n return null;\n }\n }\n // Retrieve the file from the system (local file)\n async getFileFromSystem(filePath) {\n try {\n // This is a simplified version. In a real-world scenario,\n // you might need to handle different types of paths or use a file system API.\n const response = await fetch(filePath);\n const blob = await response.blob();\n return new File([blob], filePath.split('/').pop() || 'file', {\n type: blob.type,\n });\n }\n catch (error) {\n console.error('Error getting file from system:', error);\n return null;\n }\n }\n async acknowledgeEvent(_options) {\n // Web uploads run in-process; events are not persisted for replay.\n }\n async getPluginVersion() {\n return { version: 'web' };\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin","openDB"],"mappings":"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"}
|
package/dist/plugin.js
CHANGED
|
@@ -40,6 +40,18 @@ var capacitorCapacitorUpdater = (function (exports, core, idb) {
|
|
|
40
40
|
this.doUpload(id, options);
|
|
41
41
|
return { id };
|
|
42
42
|
}
|
|
43
|
+
async uploadMultipart(options) {
|
|
44
|
+
var _a, _b;
|
|
45
|
+
return this.startUpload({
|
|
46
|
+
filePath: options.filePath,
|
|
47
|
+
serverUrl: options.url,
|
|
48
|
+
headers: (_a = options.headers) !== null && _a !== void 0 ? _a : {},
|
|
49
|
+
method: 'POST',
|
|
50
|
+
uploadType: 'multipart',
|
|
51
|
+
fileField: options.fieldName,
|
|
52
|
+
parameters: (_b = options.fields) !== null && _b !== void 0 ? _b : {},
|
|
53
|
+
});
|
|
54
|
+
}
|
|
43
55
|
async removeUpload(options) {
|
|
44
56
|
console.log('removeUpload', options);
|
|
45
57
|
const upload = this.uploads.get(options.id);
|
package/dist/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sources":["esm/index.js","esm/PathHelper.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst Uploader = registerPlugin('Uploader', {\n web: () => import('./web').then((m) => new m.UploaderWeb()),\n});\nexport * from './definitions';\nexport { Uploader };\n//# sourceMappingURL=index.js.map","export class PathHelper {\n // Check if the path follows the idb://[databaseName]/[storeName]/[key] format\n static isIndexedDBPath(path) {\n const regex = /^idb:\\/\\/([^/]+)\\/([^/]+)\\/(.+)$/;\n return regex.test(path);\n }\n // Parse the path to extract database, storeName, and key\n static parseIndexedDBPath(path) {\n const regex = /^idb:\\/\\/([^/]+)\\/([^/]+)\\/(.+)$/;\n const match = path.match(regex);\n if (!match) {\n throw new Error('Invalid IndexedDB path format');\n }\n return {\n database: match[1],\n storeName: match[2],\n key: match[3],\n };\n }\n}\n//# sourceMappingURL=PathHelper.js.map","import { WebPlugin } from '@capacitor/core';\nimport { openDB } from 'idb';\nimport { PathHelper } from './PathHelper';\nexport class UploaderWeb extends WebPlugin {\n constructor() {\n super(...arguments);\n this.uploads = new Map();\n }\n async startUpload(options) {\n console.log('startUpload', options);\n const id = Math.random().toString(36).substring(2, 15);\n const controller = new AbortController();\n const maxRetries = options.maxRetries || 3;\n this.uploads.set(id, { controller, retries: maxRetries });\n this.doUpload(id, options);\n return { id };\n }\n async removeUpload(options) {\n console.log('removeUpload', options);\n const upload = this.uploads.get(options.id);\n if (upload) {\n upload.controller.abort();\n this.uploads.delete(options.id);\n this.notifyListeners('events', {\n name: 'cancelled',\n id: options.id,\n payload: {},\n });\n }\n }\n async doUpload(id, options) {\n var _a, _b, _c;\n const { serverUrl, headers = {}, method = 'POST', parameters = {} } = options;\n const upload = this.uploads.get(id);\n if (!upload)\n return;\n try {\n const files = this.normalizeFiles(options);\n if (files.length === 0)\n throw new Error('Missing required parameter: filePath or files');\n const resolvedMethod = method.toUpperCase();\n const uploadType = (_a = options.uploadType) !== null && _a !== void 0 ? _a : (resolvedMethod === 'PUT' ? 'binary' : 'multipart');\n let body;\n if (resolvedMethod === 'PUT' || uploadType === 'binary') {\n if (files.length !== 1)\n throw new Error('Binary uploads only support a single file');\n const file = await this.getFileFromPath(files[0].filePath);\n if (!file)\n throw new Error('File not found');\n body = file;\n }\n else {\n const formData = new FormData();\n for (const fileOption of files) {\n const file = await this.getFileFromPath(fileOption.filePath);\n if (!file)\n throw new Error('File not found');\n const fieldName = (_c = (_b = fileOption.fieldName) !== null && _b !== void 0 ? _b : options.fileField) !== null && _c !== void 0 ? _c : 'file';\n formData.append(fieldName, file);\n }\n for (const [key, value] of Object.entries(parameters)) {\n formData.append(key, value);\n }\n body = formData;\n }\n const response = await fetch(serverUrl, {\n method: resolvedMethod,\n headers,\n body,\n signal: upload.controller.signal,\n });\n if (!response.ok)\n throw new Error(`HTTP error! status: ${response.status}`);\n this.notifyListeners('events', {\n name: 'completed',\n id,\n payload: { statusCode: response.status },\n });\n this.uploads.delete(id);\n }\n catch (error) {\n if (error.name === 'AbortError')\n return;\n if (upload.retries > 0) {\n upload.retries--;\n console.log(`Retrying upload (retries left: ${upload.retries})`);\n setTimeout(() => this.doUpload(id, options), 1000);\n }\n else {\n this.notifyListeners('events', {\n name: 'failed',\n id,\n payload: { error: error.message },\n });\n this.uploads.delete(id);\n }\n }\n }\n normalizeFiles(options) {\n if (options.files && options.files.length > 0)\n return options.files;\n if (options.filePath) {\n return [\n {\n filePath: options.filePath,\n fieldName: options.fileField,\n mimeType: options.mimeType,\n },\n ];\n }\n return [];\n }\n async getFileFromPath(filePath) {\n // Check if the path is an IndexedDB path\n if (PathHelper.isIndexedDBPath(filePath)) {\n return this.getFileFromIndexedDB(filePath);\n }\n // Otherwise, treat it as a file path from the system\n return this.getFileFromSystem(filePath);\n }\n // Retrieve the file from IndexedDB\n async getFileFromIndexedDB(filePath) {\n // Parse the path to get the database, store name, and key\n const { database, storeName, key } = PathHelper.parseIndexedDBPath(filePath);\n try {\n // Open the IndexedDB database and access the object store\n const db = await openDB(database, 1, {\n upgrade(db) {\n if (!db.objectStoreNames.contains(storeName)) {\n db.createObjectStore(storeName);\n }\n },\n });\n // Get the blob from the store\n const blob = await db.get(storeName, key);\n if (!blob) {\n console.error(`File with key \"${key}\" not found in store \"${storeName}\" in database \"${database}\"`);\n return null;\n }\n // Convert the Blob to a File object\n return new File([blob], key, { type: blob.type });\n }\n catch (error) {\n console.error('Error retrieving file from IndexedDB:', error);\n return null;\n }\n }\n // Retrieve the file from the system (local file)\n async getFileFromSystem(filePath) {\n try {\n // This is a simplified version. In a real-world scenario,\n // you might need to handle different types of paths or use a file system API.\n const response = await fetch(filePath);\n const blob = await response.blob();\n return new File([blob], filePath.split('/').pop() || 'file', {\n type: blob.type,\n });\n }\n catch (error) {\n console.error('Error getting file from system:', error);\n return null;\n }\n }\n async acknowledgeEvent(_options) {\n // Web uploads run in-process; events are not persisted for replay.\n }\n async getPluginVersion() {\n return { version: 'web' };\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin","openDB"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"plugin.js","sources":["esm/index.js","esm/PathHelper.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst Uploader = registerPlugin('Uploader', {\n web: () => import('./web').then((m) => new m.UploaderWeb()),\n});\nexport * from './definitions';\nexport { Uploader };\n//# sourceMappingURL=index.js.map","export class PathHelper {\n // Check if the path follows the idb://[databaseName]/[storeName]/[key] format\n static isIndexedDBPath(path) {\n const regex = /^idb:\\/\\/([^/]+)\\/([^/]+)\\/(.+)$/;\n return regex.test(path);\n }\n // Parse the path to extract database, storeName, and key\n static parseIndexedDBPath(path) {\n const regex = /^idb:\\/\\/([^/]+)\\/([^/]+)\\/(.+)$/;\n const match = path.match(regex);\n if (!match) {\n throw new Error('Invalid IndexedDB path format');\n }\n return {\n database: match[1],\n storeName: match[2],\n key: match[3],\n };\n }\n}\n//# sourceMappingURL=PathHelper.js.map","import { WebPlugin } from '@capacitor/core';\nimport { openDB } from 'idb';\nimport { PathHelper } from './PathHelper';\nexport class UploaderWeb extends WebPlugin {\n constructor() {\n super(...arguments);\n this.uploads = new Map();\n }\n async startUpload(options) {\n console.log('startUpload', options);\n const id = Math.random().toString(36).substring(2, 15);\n const controller = new AbortController();\n const maxRetries = options.maxRetries || 3;\n this.uploads.set(id, { controller, retries: maxRetries });\n this.doUpload(id, options);\n return { id };\n }\n async uploadMultipart(options) {\n var _a, _b;\n return this.startUpload({\n filePath: options.filePath,\n serverUrl: options.url,\n headers: (_a = options.headers) !== null && _a !== void 0 ? _a : {},\n method: 'POST',\n uploadType: 'multipart',\n fileField: options.fieldName,\n parameters: (_b = options.fields) !== null && _b !== void 0 ? _b : {},\n });\n }\n async removeUpload(options) {\n console.log('removeUpload', options);\n const upload = this.uploads.get(options.id);\n if (upload) {\n upload.controller.abort();\n this.uploads.delete(options.id);\n this.notifyListeners('events', {\n name: 'cancelled',\n id: options.id,\n payload: {},\n });\n }\n }\n async doUpload(id, options) {\n var _a, _b, _c;\n const { serverUrl, headers = {}, method = 'POST', parameters = {} } = options;\n const upload = this.uploads.get(id);\n if (!upload)\n return;\n try {\n const files = this.normalizeFiles(options);\n if (files.length === 0)\n throw new Error('Missing required parameter: filePath or files');\n const resolvedMethod = method.toUpperCase();\n const uploadType = (_a = options.uploadType) !== null && _a !== void 0 ? _a : (resolvedMethod === 'PUT' ? 'binary' : 'multipart');\n let body;\n if (resolvedMethod === 'PUT' || uploadType === 'binary') {\n if (files.length !== 1)\n throw new Error('Binary uploads only support a single file');\n const file = await this.getFileFromPath(files[0].filePath);\n if (!file)\n throw new Error('File not found');\n body = file;\n }\n else {\n const formData = new FormData();\n for (const fileOption of files) {\n const file = await this.getFileFromPath(fileOption.filePath);\n if (!file)\n throw new Error('File not found');\n const fieldName = (_c = (_b = fileOption.fieldName) !== null && _b !== void 0 ? _b : options.fileField) !== null && _c !== void 0 ? _c : 'file';\n formData.append(fieldName, file);\n }\n for (const [key, value] of Object.entries(parameters)) {\n formData.append(key, value);\n }\n body = formData;\n }\n const response = await fetch(serverUrl, {\n method: resolvedMethod,\n headers,\n body,\n signal: upload.controller.signal,\n });\n if (!response.ok)\n throw new Error(`HTTP error! status: ${response.status}`);\n this.notifyListeners('events', {\n name: 'completed',\n id,\n payload: { statusCode: response.status },\n });\n this.uploads.delete(id);\n }\n catch (error) {\n if (error.name === 'AbortError')\n return;\n if (upload.retries > 0) {\n upload.retries--;\n console.log(`Retrying upload (retries left: ${upload.retries})`);\n setTimeout(() => this.doUpload(id, options), 1000);\n }\n else {\n this.notifyListeners('events', {\n name: 'failed',\n id,\n payload: { error: error.message },\n });\n this.uploads.delete(id);\n }\n }\n }\n normalizeFiles(options) {\n if (options.files && options.files.length > 0)\n return options.files;\n if (options.filePath) {\n return [\n {\n filePath: options.filePath,\n fieldName: options.fileField,\n mimeType: options.mimeType,\n },\n ];\n }\n return [];\n }\n async getFileFromPath(filePath) {\n // Check if the path is an IndexedDB path\n if (PathHelper.isIndexedDBPath(filePath)) {\n return this.getFileFromIndexedDB(filePath);\n }\n // Otherwise, treat it as a file path from the system\n return this.getFileFromSystem(filePath);\n }\n // Retrieve the file from IndexedDB\n async getFileFromIndexedDB(filePath) {\n // Parse the path to get the database, store name, and key\n const { database, storeName, key } = PathHelper.parseIndexedDBPath(filePath);\n try {\n // Open the IndexedDB database and access the object store\n const db = await openDB(database, 1, {\n upgrade(db) {\n if (!db.objectStoreNames.contains(storeName)) {\n db.createObjectStore(storeName);\n }\n },\n });\n // Get the blob from the store\n const blob = await db.get(storeName, key);\n if (!blob) {\n console.error(`File with key \"${key}\" not found in store \"${storeName}\" in database \"${database}\"`);\n return null;\n }\n // Convert the Blob to a File object\n return new File([blob], key, { type: blob.type });\n }\n catch (error) {\n console.error('Error retrieving file from IndexedDB:', error);\n return null;\n }\n }\n // Retrieve the file from the system (local file)\n async getFileFromSystem(filePath) {\n try {\n // This is a simplified version. In a real-world scenario,\n // you might need to handle different types of paths or use a file system API.\n const response = await fetch(filePath);\n const blob = await response.blob();\n return new File([blob], filePath.split('/').pop() || 'file', {\n type: blob.type,\n });\n }\n catch (error) {\n console.error('Error getting file from system:', error);\n return null;\n }\n }\n async acknowledgeEvent(_options) {\n // Web uploads run in-process; events are not persisted for replay.\n }\n async getPluginVersion() {\n return { version: 'web' };\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin","openDB"],"mappings":"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"}
|
|
@@ -3,11 +3,12 @@ import Capacitor
|
|
|
3
3
|
|
|
4
4
|
@objc(UploaderPlugin)
|
|
5
5
|
public class UploaderPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
6
|
-
private let pluginVersion: String = "8.3.
|
|
6
|
+
private let pluginVersion: String = "8.3.2"
|
|
7
7
|
public let identifier = "UploaderPlugin"
|
|
8
8
|
public let jsName = "Uploader"
|
|
9
9
|
public let pluginMethods: [CAPPluginMethod] = [
|
|
10
10
|
CAPPluginMethod(name: "startUpload", returnType: CAPPluginReturnPromise),
|
|
11
|
+
CAPPluginMethod(name: "uploadMultipart", returnType: CAPPluginReturnPromise),
|
|
11
12
|
CAPPluginMethod(name: "removeUpload", returnType: CAPPluginReturnPromise),
|
|
12
13
|
CAPPluginMethod(name: "getPluginVersion", returnType: CAPPluginReturnPromise),
|
|
13
14
|
CAPPluginMethod(name: "acknowledgeEvent", returnType: CAPPluginReturnPromise)
|
|
@@ -69,6 +70,40 @@ public class UploaderPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
69
70
|
}
|
|
70
71
|
}
|
|
71
72
|
|
|
73
|
+
@objc func uploadMultipart(_ call: CAPPluginCall) {
|
|
74
|
+
guard let serverUrl = call.getString("url"), !serverUrl.isEmpty else {
|
|
75
|
+
call.reject("Missing required parameter: url")
|
|
76
|
+
return
|
|
77
|
+
}
|
|
78
|
+
guard let filePath = call.getString("filePath"), !filePath.isEmpty else {
|
|
79
|
+
call.reject("Missing required parameter: filePath")
|
|
80
|
+
return
|
|
81
|
+
}
|
|
82
|
+
guard let fieldName = call.getString("fieldName"), !fieldName.isEmpty else {
|
|
83
|
+
call.reject("Missing required parameter: fieldName")
|
|
84
|
+
return
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
let headers = (call.getObject("headers") ?? [:]).compactMapValues { $0 as? String }
|
|
88
|
+
let fields = (call.getObject("fields") ?? [:]).compactMapValues { $0 as? String }
|
|
89
|
+
let options: [String: Any] = [
|
|
90
|
+
"headers": headers,
|
|
91
|
+
"parameters": fields,
|
|
92
|
+
"method": "POST",
|
|
93
|
+
"uploadType": "multipart",
|
|
94
|
+
"fileField": fieldName
|
|
95
|
+
]
|
|
96
|
+
|
|
97
|
+
Task {
|
|
98
|
+
do {
|
|
99
|
+
let id = try await implementation.startUpload(filePath, serverUrl, options, maxRetries: 3)
|
|
100
|
+
call.resolve(["id": id])
|
|
101
|
+
} catch {
|
|
102
|
+
call.reject("Failed to start multipart upload: \(error.localizedDescription)")
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
72
107
|
@objc func acknowledgeEvent(_ call: CAPPluginCall) {
|
|
73
108
|
guard let eventId = call.getString("eventId"), !eventId.isEmpty else {
|
|
74
109
|
call.reject("Missing required parameter: eventId")
|