Skip to content

Commit

Permalink
fix: cancelUpload add cancel all
Browse files Browse the repository at this point in the history
  • Loading branch information
numandev1 committed Nov 15, 2023
1 parent b612db3 commit a03fc79
Show file tree
Hide file tree
Showing 15 changed files with 246 additions and 29 deletions.
60 changes: 60 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,53 @@ const uploadResult = await backgroundUpload(
);
```

### Cancel Background Upload
for cancellation Upload, there is two ways
1. by calling, cancelUpload function
2. by calling abort function

##### cancelUpload (support single and all)
```js
import { cancelUpload, backgroundUpload } from 'react-native-compressor';

// if we will call without passing any param then it will remove last pushed uploading
cancelUpload()

// if you pass true as second param then it will cancel all the uploading
cancelUpload("",true)

// if there is multiple files are uploading, and you wanna cancel specific uploading then you pass specific video id like this
let videoId=''
const uploadResult = await backgroundUpload(
url,
fileUrl,
{ httpMethod: 'PUT', getCancellationId: (cancellationId) =>(videoId = cancellationId), },
(written, total) => {
console.log(written, total);
}
);
cancelUpload(videoId)
```

##### cancel by calling abort
```js
import { backgroundUpload } from 'react-native-compressor';

const abortSignalRef = useRef(new AbortController());

const uploadResult = await backgroundUpload(
url,
fileUrl,
{ httpMethod: 'PUT' },
(written, total) => {
console.log(written, total);
},
abortSignalRef.current.signal
);

abortSignalRef.current?.abort(); // this will cancel uploading
```
### Download File
```js
Expand Down Expand Up @@ -493,12 +540,25 @@ export declare type UploaderOptions = (
) & {
headers?: Record<string, string>;
httpMethod?: UploaderHttpMethod;
getCancellationId?: (cancellationId: string) => void;
};
```

**Note:** some of the uploader code is borrowed from [Expo](https://github.com/expo/expo)
I tested file uploader on this backend [Nodejs-File-Uploader](https://github.com/numandev1/nodejs-file-uploader)

### Cancel Background Upload
for cancellation Upload, there is two ways, you can use one of it
- ##### cancelUpload: ( uuid?: string, shouldCancelAll?: boolean) => void
1. If we call without passing any param then it will remove the last pushed uploading
2. If you pass true as the second param then it will cancel all the uploading
3. if there is multiple files are uploading, and you wanna cancel specific uploading then you pass a specific video ID like this

- ##### we can use [AbortController](https://github.com/facebook/react-native/blob/255fef5263afdf9933ba2f8a3dbcbca39ea9928a/packages/react-native/types/modules/globals.d.ts#L531) in backgroundUpload [Usage](#cancel-background-upload)
`const abortSignalRef = useRef(new AbortController());`

`abortSignalRef.current?.abort();`

### Download

- ##### download: ( fileUrl: string, downloadProgress?: (progress: number) => void, progressDivider?: number ) => Promise< string >
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ class CompressorModule(private val reactContext: ReactApplicationContext) : Comp
}

@ReactMethod
override fun cancelUpload() {
uploader.cancelUpload()
override fun cancelUpload(uuid: String,shouldCancelAll:Boolean) {
uploader.cancelUpload(uuid,shouldCancelAll)
}

@ReactMethod
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.reactnativecompressor.Utils

import okhttp3.Call

class HttpCallManager {
private var resumableCalls: MutableMap<String, Call?> = HashMap()

fun registerTask(call: Call, uuid: String) {
resumableCalls[uuid] = call
}

fun taskForId(uuid: String): Call? {
return resumableCalls[uuid]
}

// will use in future
fun downloadTaskForId(uuid: String): Call? {
return taskForId(uuid)
}

fun uploadTaskForId(uuid: String): Call? {
return taskForId(uuid)
}

fun taskPop(): Call? {
val lastUuid = resumableCalls.keys.lastOrNull()
val lastCall = resumableCalls.remove(lastUuid)
return lastCall
}

fun unregisterTask(uuid: String) {
resumableCalls.remove(uuid)
}

fun cancelAllTasks() {
for ((_, call) in resumableCalls) {
call?.cancel()
}
resumableCalls.clear()
}
}
21 changes: 16 additions & 5 deletions android/src/main/java/com/reactnativecompressor/Utils/Uploader.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class Uploader(private val reactContext: ReactApplicationContext) {
val TAG = "asyncTaskUploader"
var client: OkHttpClient? = null
val MIN_EVENT_DT_MS: Long = 100
private var currentCall: Call? = null
val httpCallManager = HttpCallManager()

fun upload(
fileUriString: String,
Expand Down Expand Up @@ -59,12 +59,12 @@ class Uploader(private val reactContext: ReactApplicationContext) {

okHttpClient?.let {
val call = it.newCall(request)
currentCall = call
httpCallManager.registerTask(call,uuid)
call.enqueue(
object : Callback {
override fun onFailure(call: Call, e: IOException) {
Log.e(TAG, e.message.toString())
promise.reject(TAG, e.message, e)
promise.reject(TAG, e.message)
}

override fun onResponse(call: Call, response: Response) {
Expand Down Expand Up @@ -198,7 +198,18 @@ class Uploader(private val reactContext: ReactApplicationContext) {
return responseHeaders
}

fun cancelUpload() {
currentCall?.cancel()
fun cancelUpload(uuid:String,shouldCancelAll:Boolean) {
if(shouldCancelAll)
{
httpCallManager.cancelAllTasks()
}
else if(uuid=="")
{
httpCallManager.taskPop()?.cancel()
}
else
{
httpCallManager.uploadTaskForId(uuid)?.cancel()
}
}
}
2 changes: 1 addition & 1 deletion android/src/oldarch/CompressorSpec.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ abstract class CompressorSpec(context: ReactApplicationContext?) : ReactContextB
abstract fun compress(fileUrl: String, optionMap: ReadableMap, promise: Promise)
abstract fun cancelCompression(uuid: String)
abstract fun upload(fileUrl: String, options: ReadableMap, promise: Promise)
abstract fun cancelUpload()
abstract fun cancelUpload(uuid: String, shouldCancelAll:Boolean)

abstract fun download(fileUrl: String, options: ReadableMap, promise: Promise)
abstract fun activateBackgroundTask(options: ReadableMap, promise: Promise)
Expand Down
16 changes: 12 additions & 4 deletions example/ios/CompressorExample.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,10 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = "";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = CompressorExample/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
Expand All @@ -500,6 +503,7 @@
);
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = CompressorExample;
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
Expand All @@ -512,7 +516,10 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = CompressorExample/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
Expand All @@ -526,6 +533,7 @@
);
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = CompressorExample;
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
Expand Down Expand Up @@ -595,14 +603,14 @@
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = (
"$(inherited)",
" ",
"-DRN_FABRIC_ENABLED",
);
OTHER_CPLUSPLUSFLAGS = (
"$(OTHER_CFLAGS)",
"-DFOLLY_NO_CONFIG",
"-DFOLLY_MOBILE=1",
"-DFOLLY_USE_LIBCPP=1",
" ",
"-DRN_FABRIC_ENABLED",
);
OTHER_LDFLAGS = (
"$(inherited)",
Expand Down Expand Up @@ -673,14 +681,14 @@
MTL_ENABLE_DEBUG_INFO = NO;
OTHER_CFLAGS = (
"$(inherited)",
" ",
"-DRN_FABRIC_ENABLED",
);
OTHER_CPLUSPLUSFLAGS = (
"$(OTHER_CFLAGS)",
"-DFOLLY_NO_CONFIG",
"-DFOLLY_MOBILE=1",
"-DFOLLY_USE_LIBCPP=1",
" ",
"-DRN_FABRIC_ENABLED",
);
OTHER_LDFLAGS = (
"$(inherited)",
Expand Down
4 changes: 2 additions & 2 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -880,7 +880,7 @@ PODS:
- React-Codegen
- React-RCTFabric
- ReactCommon/turbomodule/core
- react-native-compressor (1.8.16):
- react-native-compressor (1.8.17):
- hermes-engine
- RCT-Folly (= 2021.07.22.00)
- RCTRequired
Expand Down Expand Up @@ -1377,7 +1377,7 @@ SPEC CHECKSUMS:
React-jsinspector: 194e32c6aab382d88713ad3dd0025c5f5c4ee072
React-logger: cebf22b6cf43434e471dc561e5911b40ac01d289
react-native-cameraroll: 5d9523136a929b58f092fd7f0a9a13367a4b46e3
react-native-compressor: 3ad769f5bac56d7337df076a1c62e74292f7136d
react-native-compressor: 8b6e302c4531f93aeaabd9658495bf9855adf3bd
react-native-document-picker: c9ac93d7b511413f4a0ed61c92ff6c7b1bcf4f94
react-native-get-random-values: dee677497c6a740b71e5612e8dbd83e7539ed5bb
react-native-image-picker: 9b4b1d0096500050cbdabf8f4fd00b771065d983
Expand Down
19 changes: 17 additions & 2 deletions example/src/Screens/Video/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
Video,
getRealPath,
backgroundUpload,
cancelUpload,
UploadType,
UploaderHttpMethod,
createVideoThumbnail,
Expand All @@ -25,11 +26,14 @@ import { getFileInfo } from '../../Utils';
import ProgressBar from '../../Components/ProgressBar';
import type { ProgressBarRafType } from '../../Components/ProgressBar';
// const DOMAIN = 'http://localhost:8080';
const DOMAIN = 'http://192.168.1.3:8080';
const DOMAIN = 'http://192.168.1.5:8080';
const uploadPutRequest = `${DOMAIN}/upload/putRequestFile.mov`;
const uploadPutRequest1 = `${DOMAIN}/upload/putRequestFile1.mov`;
const uploadPostRequest = `${DOMAIN}/upload`;
// const uploadPostRequestFail = `${DOMAIN}/uploadFail`;
let counter1 = 0;
export default function App() {
const cancellationIdForUploadRef = useRef<string>('');
const progressRef = useRef<ProgressBarRafType>();
const abortSignalRef = useRef(new AbortController());
const cancellationIdRef = useRef<string>('');
Expand All @@ -45,6 +49,7 @@ export default function App() {
const [backgroundMode, setBackgroundMode] = useState<boolean>(false);

useEffect(() => {
counter1 = -1;
if (!sourceVideo) return;
createVideoThumbnail(sourceVideo, {})
.then((response) => setSourceVideoThumbnail(response.path))
Expand Down Expand Up @@ -242,13 +247,16 @@ export default function App() {
const headers = {
Authorization: `Bearer ABCABC`,
};
counter1++;
const result = await backgroundUpload(
uploadPutRequest,
counter1 % 2 == 0 ? uploadPutRequest : uploadPutRequest1,

Check warning on line 252 in example/src/Screens/Video/index.tsx

View workflow job for this annotation

GitHub Actions / Lint JS (eslint, prettier)

Expected '===' and instead saw '=='.
localFileUrl,
{
uploadType: UploadType.BINARY_CONTENT,
httpMethod: UploaderHttpMethod.PUT,
headers,
getCancellationId: (cancellationId) =>
(cancellationIdForUploadRef.current = cancellationId),
},
(written, total) => {
progressRef.current?.setProgress(written / total);
Expand All @@ -265,6 +273,11 @@ export default function App() {
}
};

const cancelUploader = () => {
console.log('cancelUploader', cancellationIdForUploadRef.current);
cancelUpload(cancellationIdForUploadRef.current);
};

const onCompressVideofromCameraoll = async () => {
const photos = await CameraRoll.getPhotos({
first: 1,
Expand Down Expand Up @@ -314,6 +327,8 @@ export default function App() {
title="Upload(Put)"
onPress={() => uploadByPutRequest('actual')}
/>

<Button title="Cancel Upload" onPress={() => cancelUploader()} />
</View>
)}
</View>
Expand Down
5 changes: 3 additions & 2 deletions ios/Compressor.mm
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,10 @@ @interface RCT_EXTERN_MODULE(Compressor, RCTEventEmitter)
withResolver:(RCTPromiseResolveBlock)resolve
withRejecter:(RCTPromiseRejectBlock)reject)

RCT_EXTERN_METHOD(cancelUpload)
RCT_EXTERN_METHOD(cancelUpload:(NSString *)uuid
withShouldCancelAll:(BOOL*)shouldCancelAll)

RCT_EXTERN_METHOD(download:(NSString *)fileUrl
RCT_EXTERN_METHOD(download:(NSString *)fileUrlu
withOptions:(NSDictionary *)options
withResolver:(RCTPromiseResolveBlock)resolve
withRejecter:(RCTPromiseRejectBlock)reject)
Expand Down
6 changes: 3 additions & 3 deletions ios/CompressorManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ class Compressor: RCTEventEmitter {
uploader.upload(filePath: filePath, options: options, resolve: resolve, reject: reject)
}

@objc(cancelUpload)
func cancelUpload() -> Void {
uploader.cancelUpload()
@objc(cancelUpload:withShouldCancelAll:)
func cancelUpload(uuid: String,shouldCancelAll:Bool) -> Void {
uploader.cancelUpload(uuid: uuid,shouldCancelAll: shouldCancelAll)
}

@objc(download:withOptions:withResolver:withRejecter:)
Expand Down
Loading

0 comments on commit a03fc79

Please sign in to comment.