@capgo/capacitor-uploader 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CapgoCapacitorUploader.podspec +17 -0
- package/Package.swift +28 -0
- package/README.md +228 -0
- package/android/build.gradle +59 -0
- package/android/src/main/AndroidManifest.xml +33 -0
- package/android/src/main/java/ee/forgr/capacitor/uploader/Uploader.java +123 -0
- package/android/src/main/java/ee/forgr/capacitor/uploader/UploaderPlugin.java +116 -0
- package/android/src/main/res/.gitkeep +0 -0
- package/dist/docs.json +310 -0
- package/dist/esm/definitions.d.ts +92 -0
- package/dist/esm/definitions.js +2 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +15 -0
- package/dist/esm/web.js +18 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +34 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +37 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Sources/UploaderPlugin/Uploader.swift +162 -0
- package/ios/Sources/UploaderPlugin/UploaderPlugin.swift +55 -0
- package/ios/Tests/UploaderPluginTests/UploaderPluginTests.swift +15 -0
- package/package.json +81 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = 'CapgoCapacitorUploader'
|
|
7
|
+
s.version = package['version']
|
|
8
|
+
s.summary = package['description']
|
|
9
|
+
s.license = package['license']
|
|
10
|
+
s.homepage = package['repository']['url']
|
|
11
|
+
s.author = package['author']
|
|
12
|
+
s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
|
|
13
|
+
s.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
|
|
14
|
+
s.ios.deployment_target = '13.0'
|
|
15
|
+
s.dependency 'Capacitor'
|
|
16
|
+
s.swift_version = '5.1'
|
|
17
|
+
end
|
package/Package.swift
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// swift-tools-version: 5.9
|
|
2
|
+
import PackageDescription
|
|
3
|
+
|
|
4
|
+
let package = Package(
|
|
5
|
+
name: "CapgoCapacitorUploader",
|
|
6
|
+
platforms: [.iOS(.v13)],
|
|
7
|
+
products: [
|
|
8
|
+
.library(
|
|
9
|
+
name: "CapgoCapacitorUploader",
|
|
10
|
+
targets: ["UploaderPlugin"])
|
|
11
|
+
],
|
|
12
|
+
dependencies: [
|
|
13
|
+
.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", branch: "main")
|
|
14
|
+
],
|
|
15
|
+
targets: [
|
|
16
|
+
.target(
|
|
17
|
+
name: "UploaderPlugin",
|
|
18
|
+
dependencies: [
|
|
19
|
+
.product(name: "Capacitor", package: "capacitor-swift-pm"),
|
|
20
|
+
.product(name: "Cordova", package: "capacitor-swift-pm")
|
|
21
|
+
],
|
|
22
|
+
path: "ios/Sources/UploaderPlugin"),
|
|
23
|
+
.testTarget(
|
|
24
|
+
name: "UploaderPluginTests",
|
|
25
|
+
dependencies: ["UploaderPlugin"],
|
|
26
|
+
path: "ios/Tests/UploaderPluginTests")
|
|
27
|
+
]
|
|
28
|
+
)
|
package/README.md
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
# @capgo/capacitor-uploader
|
|
2
|
+
<a href="https://capgo.app/"><img src='https://raw.githubusercontent.com/Cap-go/capgo/main/assets/capgo_banner.png' alt='Capgo - Instant updates for capacitor'/></a>
|
|
3
|
+
<div align="center">
|
|
4
|
+
<h2><a href="https://capgo.app/">Check out: Capgo — Instant updates for capacitor</a></h2>
|
|
5
|
+
</div>
|
|
6
|
+
|
|
7
|
+
## Uploader Plugin
|
|
8
|
+
|
|
9
|
+
This plugin provides a flexible way to upload natively files to various servers, including S3 with presigned URLs.
|
|
10
|
+
|
|
11
|
+
WIP: this is a work in progress still not ready for use
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @capgo/capacitor-uploader
|
|
17
|
+
npx cap sync
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Android:
|
|
21
|
+
|
|
22
|
+
Add the following to your `AndroidManifest.xml` file:
|
|
23
|
+
|
|
24
|
+
```xml
|
|
25
|
+
<uses-permission android:name="android.permission.INTERNET" />
|
|
26
|
+
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
|
27
|
+
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Exemple S3 upload:
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
## Example S3 upload:
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { Uploader } from '@capgo/capacitor-uploader';
|
|
37
|
+
|
|
38
|
+
async function uploadToS3(filePath: string, presignedUrl: string, fields: Record<string, string>) {
|
|
39
|
+
try {
|
|
40
|
+
const { id } = await Uploader.startUpload({
|
|
41
|
+
filePath: filePath,
|
|
42
|
+
serverUrl: presignedUrl,
|
|
43
|
+
method: 'PUT',
|
|
44
|
+
parameters: fields,
|
|
45
|
+
notificationTitle: 'Uploading to S3'
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
console.log('Upload started with ID:', id);
|
|
49
|
+
|
|
50
|
+
// Listen for upload events
|
|
51
|
+
Uploader.addListener('events', (event: UploadEvent) => {
|
|
52
|
+
if (event.name === 'uploading') {
|
|
53
|
+
console.log(`Upload progress: ${event.payload.percent}%`);
|
|
54
|
+
} else if (event.name === 'completed') {
|
|
55
|
+
console.log('Upload completed successfully');
|
|
56
|
+
} else if (event.name === 'failed') {
|
|
57
|
+
console.error('Upload failed:', event.payload.error);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.error('Failed to start upload:', error);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Exemple upload to a custom server:
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
import { Uploader } from '@capgo/capacitor-uploader';
|
|
72
|
+
|
|
73
|
+
async function uploadToCustomServer(filePath: string, serverUrl: string) {
|
|
74
|
+
try {
|
|
75
|
+
// Start the upload
|
|
76
|
+
const { id } = await Uploader.startUpload({
|
|
77
|
+
filePath: filePath,
|
|
78
|
+
serverUrl: serverUrl,
|
|
79
|
+
method: 'POST',
|
|
80
|
+
headers: {
|
|
81
|
+
'Authorization': 'Bearer your-auth-token-here'
|
|
82
|
+
},
|
|
83
|
+
parameters: {
|
|
84
|
+
'user_id': '12345',
|
|
85
|
+
'file_type': 'image'
|
|
86
|
+
},
|
|
87
|
+
notificationTitle: 'Uploading to Custom Server',
|
|
88
|
+
maxRetries: 3
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
console.log('Upload started with ID:', id);
|
|
92
|
+
|
|
93
|
+
// Listen for upload events
|
|
94
|
+
Uploader.addListener('events', (event) => {
|
|
95
|
+
switch (event.name) {
|
|
96
|
+
case 'uploading':
|
|
97
|
+
console.log(`Upload progress: ${event.payload.percent}%`);
|
|
98
|
+
break;
|
|
99
|
+
case 'completed':
|
|
100
|
+
console.log('Upload completed successfully');
|
|
101
|
+
console.log('Server response status code:', event.payload.statusCode);
|
|
102
|
+
break;
|
|
103
|
+
case 'failed':
|
|
104
|
+
console.error('Upload failed:', event.payload.error);
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Optional: Remove the upload if needed
|
|
110
|
+
// await Uploader.removeUpload({ id: id });
|
|
111
|
+
|
|
112
|
+
} catch (error) {
|
|
113
|
+
console.error('Failed to start upload:', error);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Usage
|
|
118
|
+
const filePath = 'file:///path/to/your/file.jpg';
|
|
119
|
+
const serverUrl = 'https://your-custom-server.com/upload';
|
|
120
|
+
uploadToCustomServer(filePath, serverUrl);
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## API
|
|
125
|
+
|
|
126
|
+
<docgen-index>
|
|
127
|
+
|
|
128
|
+
* [`startUpload(...)`](#startupload)
|
|
129
|
+
* [`removeUpload(...)`](#removeupload)
|
|
130
|
+
* [`addListener('events', ...)`](#addlistenerevents-)
|
|
131
|
+
* [Interfaces](#interfaces)
|
|
132
|
+
|
|
133
|
+
</docgen-index>
|
|
134
|
+
|
|
135
|
+
<docgen-api>
|
|
136
|
+
<!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
|
|
137
|
+
|
|
138
|
+
### startUpload(...)
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
startUpload(options: uploadOption) => any
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
| Param | Type |
|
|
145
|
+
| ------------- | ----------------------------------------------------- |
|
|
146
|
+
| **`options`** | <code><a href="#uploadoption">uploadOption</a></code> |
|
|
147
|
+
|
|
148
|
+
**Returns:** <code>any</code>
|
|
149
|
+
|
|
150
|
+
**Since:** 1.0.0
|
|
151
|
+
|
|
152
|
+
--------------------
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
### removeUpload(...)
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
removeUpload(options: { id: string; }) => any
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
| Param | Type |
|
|
162
|
+
| ------------- | ---------------------------- |
|
|
163
|
+
| **`options`** | <code>{ id: string; }</code> |
|
|
164
|
+
|
|
165
|
+
**Returns:** <code>any</code>
|
|
166
|
+
|
|
167
|
+
**Since:** 1.0.0
|
|
168
|
+
|
|
169
|
+
--------------------
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
### addListener('events', ...)
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
addListener(eventName: 'events', listenerFunc: (state: UploadEvent) => void) => any
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
| Param | Type |
|
|
179
|
+
| ------------------ | ----------------------------------------------------------------------- |
|
|
180
|
+
| **`eventName`** | <code>'events'</code> |
|
|
181
|
+
| **`listenerFunc`** | <code>(state: <a href="#uploadevent">UploadEvent</a>) => void</code> |
|
|
182
|
+
|
|
183
|
+
**Returns:** <code>any</code>
|
|
184
|
+
|
|
185
|
+
**Since:** 1.0.0
|
|
186
|
+
|
|
187
|
+
--------------------
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
### Interfaces
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
#### uploadOption
|
|
194
|
+
|
|
195
|
+
| Prop | Type | Default | Since |
|
|
196
|
+
| ----------------------- | --------------------------------------- | ------------------------ | ----- |
|
|
197
|
+
| **`filePath`** | <code>string</code> | | 1.0.0 |
|
|
198
|
+
| **`serverUrl`** | <code>string</code> | | 1.0.0 |
|
|
199
|
+
| **`notificationTitle`** | <code>number</code> | <code>'Uploading'</code> | 1.0.0 |
|
|
200
|
+
| **`headers`** | <code>{ [key: string]: string; }</code> | | 1.0.0 |
|
|
201
|
+
| **`method`** | <code>'PUT' \| 'POST'</code> | <code>'POST'</code> | 1.0.0 |
|
|
202
|
+
| **`mimeType`** | <code>string</code> | | 1.0.0 |
|
|
203
|
+
| **`parameters`** | <code>{ [key: string]: string; }</code> | | 1.0.0 |
|
|
204
|
+
| **`maxRetries`** | <code>number</code> | | 1.0.0 |
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
#### UploadEvent
|
|
208
|
+
|
|
209
|
+
| Prop | Type | Description | Since |
|
|
210
|
+
| ------------- | ----------------------------------------------------------------------- | -------------------------------------------- | ----- |
|
|
211
|
+
| **`name`** | <code>'uploading' \| 'completed' \| 'failed'</code> | Current status of upload, between 0 and 100. | |
|
|
212
|
+
| **`payload`** | <code>{ percent?: number; error?: string; statusCode?: number; }</code> | | 1.0.0 |
|
|
213
|
+
| **`id`** | <code>string</code> | | 1.0.0 |
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
#### PluginListenerHandle
|
|
217
|
+
|
|
218
|
+
| Prop | Type |
|
|
219
|
+
| ------------ | ------------------------- |
|
|
220
|
+
| **`remove`** | <code>() => any</code> |
|
|
221
|
+
|
|
222
|
+
</docgen-api>
|
|
223
|
+
|
|
224
|
+
### Credits:
|
|
225
|
+
|
|
226
|
+
For the inspiration and the code on ios: https://github.com/Vydia/react-native-background-upload/tree/master
|
|
227
|
+
For the API definition: https://www.npmjs.com/package/cordova-plugin-background-upload-put-s3
|
|
228
|
+
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
ext {
|
|
2
|
+
junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
|
|
3
|
+
androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.6.1'
|
|
4
|
+
androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.1.5'
|
|
5
|
+
androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.5.1'
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
buildscript {
|
|
9
|
+
repositories {
|
|
10
|
+
google()
|
|
11
|
+
mavenCentral()
|
|
12
|
+
}
|
|
13
|
+
dependencies {
|
|
14
|
+
classpath 'com.android.tools.build:gradle:8.2.1'
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
apply plugin: 'com.android.library'
|
|
19
|
+
|
|
20
|
+
android {
|
|
21
|
+
namespace "ee.forgr.capacitor.uploader"
|
|
22
|
+
compileSdk project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 34
|
|
23
|
+
defaultConfig {
|
|
24
|
+
minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 22
|
|
25
|
+
targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 34
|
|
26
|
+
versionCode 1
|
|
27
|
+
versionName "1.0"
|
|
28
|
+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
29
|
+
}
|
|
30
|
+
buildTypes {
|
|
31
|
+
release {
|
|
32
|
+
minifyEnabled false
|
|
33
|
+
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
lintOptions {
|
|
37
|
+
abortOnError false
|
|
38
|
+
}
|
|
39
|
+
compileOptions {
|
|
40
|
+
sourceCompatibility JavaVersion.VERSION_17
|
|
41
|
+
targetCompatibility JavaVersion.VERSION_17
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
repositories {
|
|
46
|
+
google()
|
|
47
|
+
mavenCentral()
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
dependencies {
|
|
52
|
+
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
|
53
|
+
implementation project(':capacitor-android')
|
|
54
|
+
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
|
|
55
|
+
implementation 'net.gotev:uploadservice:4.7.0'
|
|
56
|
+
testImplementation "junit:junit:$junitVersion"
|
|
57
|
+
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
|
|
58
|
+
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
|
|
59
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
3
|
+
package="ee.forgr.capacitor.uploader">
|
|
4
|
+
|
|
5
|
+
<application>
|
|
6
|
+
<service
|
|
7
|
+
android:name="net.gotev.uploadservice.UploadService"
|
|
8
|
+
android:enabled="true"
|
|
9
|
+
android:exported="false"
|
|
10
|
+
android:foregroundServiceType="dataSync">
|
|
11
|
+
<intent-filter>
|
|
12
|
+
<action android:name="android.intent.action.RUN" />
|
|
13
|
+
</intent-filter>
|
|
14
|
+
</service>
|
|
15
|
+
|
|
16
|
+
<service
|
|
17
|
+
android:name="net.gotev.uploadservice.UploadJobService"
|
|
18
|
+
android:enabled="true"
|
|
19
|
+
android:exported="false"
|
|
20
|
+
android:permission="android.permission.BIND_JOB_SERVICE">
|
|
21
|
+
</service>
|
|
22
|
+
|
|
23
|
+
<receiver
|
|
24
|
+
android:name="net.gotev.uploadservice.UploadServiceBroadcastReceiver"
|
|
25
|
+
android:enabled="true"
|
|
26
|
+
android:exported="false">
|
|
27
|
+
<intent-filter>
|
|
28
|
+
<action android:name="net.gotev.uploadservice.broadcast.status" />
|
|
29
|
+
</intent-filter>
|
|
30
|
+
</receiver>
|
|
31
|
+
</application>
|
|
32
|
+
|
|
33
|
+
</manifest>
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
package ee.forgr.capacitor.uploader;
|
|
2
|
+
|
|
3
|
+
import android.app.Application;
|
|
4
|
+
import android.content.Context;
|
|
5
|
+
import android.net.Uri;
|
|
6
|
+
import android.provider.OpenableColumns;
|
|
7
|
+
import android.database.Cursor;
|
|
8
|
+
|
|
9
|
+
import net.gotev.uploadservice.UploadServiceConfig;
|
|
10
|
+
import net.gotev.uploadservice.data.UploadNotificationConfig;
|
|
11
|
+
import net.gotev.uploadservice.data.UploadNotificationStatusConfig;
|
|
12
|
+
import net.gotev.uploadservice.protocols.multipart.MultipartUploadRequest;
|
|
13
|
+
import net.gotev.uploadservice.observer.request.RequestObserverDelegate;
|
|
14
|
+
|
|
15
|
+
import java.util.Map;
|
|
16
|
+
|
|
17
|
+
public class Uploader {
|
|
18
|
+
|
|
19
|
+
private final Context context;
|
|
20
|
+
private final RequestObserverDelegate delegate;
|
|
21
|
+
|
|
22
|
+
public Uploader(Context context, RequestObserverDelegate delegate) {
|
|
23
|
+
this.context = context;
|
|
24
|
+
this.delegate = delegate;
|
|
25
|
+
initializeUploadService(context);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
private void initializeUploadService(Context context) {
|
|
29
|
+
Application application = getApplication(context);
|
|
30
|
+
if (application != null) {
|
|
31
|
+
UploadServiceConfig.initialize(application, "ee.forgr.capacitor.uploader.notification_channel_id", true);
|
|
32
|
+
} else {
|
|
33
|
+
throw new IllegalStateException("Unable to get Application instance");
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
private Application getApplication(Context context) {
|
|
38
|
+
if (context == null) {
|
|
39
|
+
return null;
|
|
40
|
+
} else if (context instanceof Application) {
|
|
41
|
+
return (Application) context;
|
|
42
|
+
} else {
|
|
43
|
+
return getApplication(context.getApplicationContext());
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public String startUpload(String filePath, String serverUrl, Map<String, String> headers, Map<String, String> parameters,
|
|
48
|
+
String httpMethod, String notificationTitle, int maxRetries, String mimeType) throws Exception {
|
|
49
|
+
UploadNotificationConfig notificationConfig = createNotificationConfig(notificationTitle);
|
|
50
|
+
|
|
51
|
+
MultipartUploadRequest request = new MultipartUploadRequest(context, serverUrl)
|
|
52
|
+
.setMethod(httpMethod)
|
|
53
|
+
.addFileToUpload(filePath, "file", mimeType) // Updated this line
|
|
54
|
+
.setNotificationConfig((ctx, uploadId) -> notificationConfig)
|
|
55
|
+
.setMaxRetries(maxRetries);
|
|
56
|
+
|
|
57
|
+
// Add headers
|
|
58
|
+
for (Map.Entry<String, String> entry : headers.entrySet()) {
|
|
59
|
+
request.addHeader(entry.getKey(), entry.getValue());
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Add parameters
|
|
63
|
+
for (Map.Entry<String, String> entry : parameters.entrySet()) {
|
|
64
|
+
request.addParameter(entry.getKey(), entry.getValue());
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Set file name if it's a content URI
|
|
68
|
+
if (filePath.startsWith("content://")) {
|
|
69
|
+
Uri uri = Uri.parse(filePath);
|
|
70
|
+
String fileName = getFileNameFromUri(uri);
|
|
71
|
+
if (fileName != null) {
|
|
72
|
+
request.addParameter("filename", fileName);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Start the upload
|
|
77
|
+
return request.startUpload();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
public void removeUpload(String uploadId) {
|
|
81
|
+
net.gotev.uploadservice.UploadService.stopUpload(uploadId);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private UploadNotificationConfig createNotificationConfig(String notificationTitle) {
|
|
85
|
+
UploadNotificationStatusConfig progress = new UploadNotificationStatusConfig(notificationTitle, notificationTitle + " - In Progress");
|
|
86
|
+
UploadNotificationStatusConfig success = new UploadNotificationStatusConfig(notificationTitle, notificationTitle + " - Completed");
|
|
87
|
+
UploadNotificationStatusConfig error = new UploadNotificationStatusConfig(notificationTitle, notificationTitle + " - Error");
|
|
88
|
+
UploadNotificationStatusConfig cancelled = new UploadNotificationStatusConfig(notificationTitle, notificationTitle + " - Cancelled");
|
|
89
|
+
|
|
90
|
+
return new UploadNotificationConfig(
|
|
91
|
+
"ee.forgr.capacitor.uploader.notification_channel_id",
|
|
92
|
+
false,
|
|
93
|
+
progress,
|
|
94
|
+
success,
|
|
95
|
+
error,
|
|
96
|
+
cancelled
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
private String getFileNameFromUri(Uri uri) {
|
|
101
|
+
String result = null;
|
|
102
|
+
if (uri.getScheme().equals("content")) {
|
|
103
|
+
try (Cursor cursor = context.getContentResolver().query(uri, null, null, null, null)) {
|
|
104
|
+
if (cursor != null && cursor.moveToFirst()) {
|
|
105
|
+
int index = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
|
|
106
|
+
if (index != -1) {
|
|
107
|
+
result = cursor.getString(index);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
} catch (Exception e) {
|
|
111
|
+
e.printStackTrace();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (result == null) {
|
|
115
|
+
result = uri.getPath();
|
|
116
|
+
int cut = result.lastIndexOf('/');
|
|
117
|
+
if (cut != -1) {
|
|
118
|
+
result = result.substring(cut + 1);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return result;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
package ee.forgr.capacitor.uploader;
|
|
2
|
+
|
|
3
|
+
import android.content.Context;
|
|
4
|
+
import com.getcapacitor.JSObject;
|
|
5
|
+
import com.getcapacitor.Plugin;
|
|
6
|
+
import com.getcapacitor.PluginCall;
|
|
7
|
+
import com.getcapacitor.PluginMethod;
|
|
8
|
+
import com.getcapacitor.annotation.CapacitorPlugin;
|
|
9
|
+
|
|
10
|
+
import net.gotev.uploadservice.data.UploadInfo;
|
|
11
|
+
import net.gotev.uploadservice.network.ServerResponse;
|
|
12
|
+
import net.gotev.uploadservice.observer.request.RequestObserverDelegate;
|
|
13
|
+
|
|
14
|
+
import java.util.Map;
|
|
15
|
+
import java.util.HashMap;
|
|
16
|
+
import java.util.Iterator;
|
|
17
|
+
|
|
18
|
+
@CapacitorPlugin(name = "Uploader")
|
|
19
|
+
public class UploaderPlugin extends Plugin {
|
|
20
|
+
|
|
21
|
+
private Uploader implementation;
|
|
22
|
+
|
|
23
|
+
@Override
|
|
24
|
+
public void load() {
|
|
25
|
+
implementation = new Uploader(getContext(), new RequestObserverDelegate() {
|
|
26
|
+
@Override
|
|
27
|
+
public void onProgress(Context context, UploadInfo uploadInfo) {
|
|
28
|
+
JSObject event = new JSObject();
|
|
29
|
+
event.put("name", "uploading");
|
|
30
|
+
JSObject payload = new JSObject();
|
|
31
|
+
payload.put("percent", uploadInfo.getProgressPercent());
|
|
32
|
+
event.put("payload", payload);
|
|
33
|
+
event.put("id", uploadInfo.getUploadId());
|
|
34
|
+
notifyListeners("events", event);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@Override
|
|
38
|
+
public void onSuccess(Context context, UploadInfo uploadInfo, ServerResponse serverResponse) {
|
|
39
|
+
JSObject event = new JSObject();
|
|
40
|
+
event.put("name", "completed");
|
|
41
|
+
JSObject payload = new JSObject();
|
|
42
|
+
payload.put("statusCode", serverResponse.getCode());
|
|
43
|
+
event.put("payload", payload);
|
|
44
|
+
event.put("id", uploadInfo.getUploadId());
|
|
45
|
+
notifyListeners("events", event);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@Override
|
|
49
|
+
public void onError(Context context, UploadInfo uploadInfo, Throwable exception) {
|
|
50
|
+
JSObject event = new JSObject();
|
|
51
|
+
event.put("name", "failed");
|
|
52
|
+
JSObject payload = new JSObject();
|
|
53
|
+
payload.put("error", exception.getMessage());
|
|
54
|
+
event.put("payload", payload);
|
|
55
|
+
event.put("id", uploadInfo.getUploadId());
|
|
56
|
+
notifyListeners("events", event);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@Override
|
|
60
|
+
public void onCompleted(Context context, UploadInfo uploadInfo) {
|
|
61
|
+
// This method is called after onSuccess or onError
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@Override
|
|
65
|
+
public void onCompletedWhileNotObserving() {
|
|
66
|
+
// This method is called when the upload completes while the observer is not registered
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
@PluginMethod
|
|
72
|
+
public void startUpload(PluginCall call) {
|
|
73
|
+
String filePath = call.getString("filePath");
|
|
74
|
+
String serverUrl = call.getString("serverUrl");
|
|
75
|
+
JSObject headersObj = call.getObject("headers", new JSObject());
|
|
76
|
+
JSObject parametersObj = call.getObject("parameters", new JSObject());
|
|
77
|
+
String httpMethod = call.getString("method", "POST");
|
|
78
|
+
String notificationTitle = call.getString("notificationTitle", "File Upload");
|
|
79
|
+
int maxRetries = call.getInt("maxRetries", 2);
|
|
80
|
+
String mimeType = call.getString("mimeType"); // Add this line
|
|
81
|
+
|
|
82
|
+
Map<String, String> headers = JSObjectToMap(headersObj);
|
|
83
|
+
Map<String, String> parameters = JSObjectToMap(parametersObj);
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
String id = implementation.startUpload(filePath, serverUrl, headers, parameters, httpMethod, notificationTitle, maxRetries, mimeType);
|
|
87
|
+
JSObject result = new JSObject();
|
|
88
|
+
result.put("id", id);
|
|
89
|
+
call.resolve(result);
|
|
90
|
+
} catch (Exception e) {
|
|
91
|
+
call.reject(e.getMessage());
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
@PluginMethod
|
|
96
|
+
public void removeUpload(PluginCall call) {
|
|
97
|
+
String id = call.getString("id");
|
|
98
|
+
try {
|
|
99
|
+
implementation.removeUpload(id);
|
|
100
|
+
call.resolve();
|
|
101
|
+
} catch (Exception e) {
|
|
102
|
+
call.reject(e.getMessage());
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
private Map<String, String> JSObjectToMap(JSObject object) {
|
|
107
|
+
Map<String, String> map = new HashMap<>();
|
|
108
|
+
if (object != null) {
|
|
109
|
+
for (Iterator<String> it = object.keys(); it.hasNext(); ) {
|
|
110
|
+
String key = it.next();
|
|
111
|
+
map.put(key, object.getString(key));
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return map;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
File without changes
|