react-native-compressor 1.7.2 → 1.8.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/README.md +51 -8
- package/android/build.gradle +9 -0
- package/android/src/main/java/com/reactnativecompressor/Audio/AudioCompressor.kt +527 -0
- package/android/src/main/java/com/reactnativecompressor/Audio/AudioMain.kt +31 -0
- package/android/src/main/java/com/reactnativecompressor/CompressorModule.kt +169 -0
- package/android/src/main/java/com/reactnativecompressor/CompressorPackage.kt +34 -0
- package/android/src/main/java/com/reactnativecompressor/Image/ImageCompressor.kt +199 -0
- package/android/src/main/java/com/reactnativecompressor/Image/ImageCompressorOptions.kt +57 -0
- package/android/src/main/java/com/reactnativecompressor/Image/ImageMain.kt +31 -0
- package/android/src/main/java/com/reactnativecompressor/Image/ImageSize.kt +3 -0
- package/android/src/main/java/com/reactnativecompressor/Utils/Downloader.kt +119 -0
- package/android/src/main/java/com/reactnativecompressor/Utils/EventEmitterHandler.kt +66 -0
- package/android/src/main/java/com/reactnativecompressor/Utils/MediaCache.kt +61 -0
- package/android/src/main/java/com/reactnativecompressor/Utils/RealPathUtil.kt +177 -0
- package/android/src/main/java/com/reactnativecompressor/Utils/Uploader.kt +117 -0
- package/android/src/main/java/com/reactnativecompressor/Utils/Utils.kt +162 -0
- package/android/src/main/java/com/reactnativecompressor/Utils/createVideoThumbnail.kt +158 -0
- package/android/src/main/java/com/reactnativecompressor/Video/AutoVideoCompression.kt +63 -0
- package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressorHelper.kt +125 -0
- package/android/src/main/java/com/reactnativecompressor/Video/VideoMain.kt +86 -0
- package/android/src/newarch/CompressorSpec.kt +5 -0
- package/android/src/oldarch/CompressorSpec.kt +34 -0
- package/ios/Audio/AudioMain.swift +115 -0
- package/ios/Compressor-Bridging-Header.h +1 -2
- package/ios/Compressor.h +0 -8
- package/ios/Compressor.mm +37 -389
- package/ios/CompressorManager.swift +107 -0
- package/ios/Image/ImageCompressor.swift +354 -0
- package/ios/Image/ImageCompressorOptions.swift +93 -0
- package/ios/Image/ImageMain.swift +27 -0
- package/ios/Utils/CreateVideoThumbnail.swift +111 -0
- package/ios/Utils/Downloader.swift +157 -0
- package/ios/Utils/EventEmitterHandler.swift +54 -0
- package/ios/Utils/MediaCache.swift +48 -0
- package/ios/Utils/Uploader.swift +99 -0
- package/ios/Utils/Utils.swift +110 -0
- package/ios/Video/{VideoCompressor.swift → VideoMain.swift} +167 -146
- package/lib/commonjs/Image/index.js +1 -1
- package/lib/commonjs/Image/index.js.map +1 -1
- package/lib/commonjs/Main.js +1 -8
- package/lib/commonjs/Main.js.map +1 -1
- package/lib/commonjs/Spec/NativeCompressor.js.map +1 -1
- package/lib/commonjs/Video/index.js +4 -33
- package/lib/commonjs/Video/index.js.map +1 -1
- package/lib/commonjs/expo-plugin/compressor.js.map +1 -1
- package/lib/commonjs/index.js +25 -6
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/utils/Downloader.js +38 -0
- package/lib/commonjs/utils/Downloader.js.map +1 -0
- package/lib/commonjs/utils/Uploader.js +40 -0
- package/lib/commonjs/utils/Uploader.js.map +1 -0
- package/lib/commonjs/utils/index.js +47 -1
- package/lib/commonjs/utils/index.js.map +1 -1
- package/lib/module/Image/index.js +1 -1
- package/lib/module/Image/index.js.map +1 -1
- package/lib/module/Main.js +1 -7
- package/lib/module/Main.js.map +1 -1
- package/lib/module/Spec/NativeCompressor.js.map +1 -1
- package/lib/module/Video/index.js +5 -33
- package/lib/module/Video/index.js.map +1 -1
- package/lib/module/expo-plugin/compressor.js.map +1 -1
- package/lib/module/index.js +9 -7
- package/lib/module/index.js.map +1 -1
- package/lib/module/utils/Downloader.js +31 -0
- package/lib/module/utils/Downloader.js.map +1 -0
- package/lib/module/utils/Uploader.js +33 -0
- package/lib/module/utils/Uploader.js.map +1 -0
- package/lib/module/utils/index.js +9 -0
- package/lib/module/utils/index.js.map +1 -1
- package/lib/typescript/Image/index.d.ts +4 -0
- package/lib/typescript/Image/index.d.ts.map +1 -1
- package/lib/typescript/Main.d.ts +1 -2
- package/lib/typescript/Main.d.ts.map +1 -1
- package/lib/typescript/Spec/NativeCompressor.d.ts +16 -2
- package/lib/typescript/Spec/NativeCompressor.d.ts.map +1 -1
- package/lib/typescript/Video/index.d.ts +4 -28
- package/lib/typescript/Video/index.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +7 -4
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/utils/Downloader.d.ts +2 -0
- package/lib/typescript/utils/Downloader.d.ts.map +1 -0
- package/lib/typescript/utils/Uploader.d.ts +28 -0
- package/lib/typescript/utils/Uploader.d.ts.map +1 -0
- package/lib/typescript/utils/index.d.ts +4 -1
- package/lib/typescript/utils/index.d.ts.map +1 -1
- package/package.json +6 -4
- package/src/Image/index.tsx +5 -1
- package/src/Main.tsx +1 -15
- package/src/Spec/NativeCompressor.ts +25 -2
- package/src/Video/index.tsx +11 -84
- package/src/expo-plugin/compressor.ts +1 -1
- package/src/index.tsx +12 -3
- package/src/utils/Downloader.tsx +38 -0
- package/src/utils/Uploader.tsx +78 -0
- package/src/utils/index.tsx +15 -0
- package/android/src/main/java/com/reactnativecompressor/Audio/AudioCompressor.java +0 -605
- package/android/src/main/java/com/reactnativecompressor/CompressorModule.java +0 -220
- package/android/src/main/java/com/reactnativecompressor/CompressorPackage.java +0 -58
- package/android/src/main/java/com/reactnativecompressor/Image/ImageCompressor.java +0 -257
- package/android/src/main/java/com/reactnativecompressor/Image/utils/ImageCompressorOptions.java +0 -69
- package/android/src/main/java/com/reactnativecompressor/Image/utils/ImageSize.java +0 -13
- package/android/src/main/java/com/reactnativecompressor/Utils/FileUplaoder/FileUploadHelper.java +0 -39
- package/android/src/main/java/com/reactnativecompressor/Utils/FileUplaoder/FileUploader.java +0 -129
- package/android/src/main/java/com/reactnativecompressor/Utils/MediaCache.java +0 -65
- package/android/src/main/java/com/reactnativecompressor/Utils/RealPathUtil.java +0 -210
- package/android/src/main/java/com/reactnativecompressor/Utils/Utils.java +0 -272
- package/android/src/main/java/com/reactnativecompressor/Video/AutoVideoCompression/AutoVideoCompression.java +0 -87
- package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressorHelper.java +0 -182
- package/android/src/main/java/com/reactnativecompressor/Video/VideoModule.java +0 -112
- package/android/src/newarch/CompressorSpec.java +0 -9
- package/android/src/newarch/VideoCompressorSpec.java +0 -9
- package/android/src/oldarch/CompressorSpec.java +0 -34
- package/android/src/oldarch/VideoCompressorSpec.java +0 -26
- package/ios/Image/ImageCompressor.h +0 -22
- package/ios/Image/ImageCompressor.m +0 -540
- package/ios/Image/ImageCompressorOptions.h +0 -28
- package/ios/Image/ImageCompressorOptions.m +0 -97
- package/ios/Utils/Downloader.h +0 -16
- package/ios/Utils/Downloader.m +0 -150
- package/ios/Utils/MediaCache.h +0 -11
- package/ios/Utils/MediaCache.m +0 -51
- package/ios/Video/VideoCompressor.h +0 -5
- package/ios/Video/VideoCompressor.m +0 -1
- package/lib/commonjs/Spec/NativeVideoCompressor.js +0 -10
- package/lib/commonjs/Spec/NativeVideoCompressor.js.map +0 -1
- package/lib/module/Spec/NativeVideoCompressor.js +0 -3
- package/lib/module/Spec/NativeVideoCompressor.js.map +0 -1
- package/lib/typescript/Spec/NativeVideoCompressor.d.ts +0 -13
- package/lib/typescript/Spec/NativeVideoCompressor.d.ts.map +0 -1
- package/src/Spec/NativeVideoCompressor.ts +0 -14
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
class Downloader: NSObject, URLSessionDownloadDelegate {
|
|
4
|
+
private var session: URLSession?
|
|
5
|
+
private var task: URLSessionDownloadTask?
|
|
6
|
+
private var statusCode: NSNumber?
|
|
7
|
+
private var lastProgressEmitTimestamp: TimeInterval = 0
|
|
8
|
+
private var lastProgressValue: NSNumber?
|
|
9
|
+
private var contentLength: NSNumber?
|
|
10
|
+
private var bytesWritten: NSNumber?
|
|
11
|
+
private var resumeData: Data?
|
|
12
|
+
private var toFile: String?
|
|
13
|
+
private var progressDivider: Int=0
|
|
14
|
+
|
|
15
|
+
typealias ProgressCallback = (NSNumber) -> Void
|
|
16
|
+
typealias DownloadCompleteCallback = (String) -> Void
|
|
17
|
+
typealias ErrorCallback = (Error) -> Void
|
|
18
|
+
|
|
19
|
+
var globalProgressCallback: ProgressCallback?
|
|
20
|
+
var globalDownloadCompleteCallback: DownloadCompleteCallback?
|
|
21
|
+
var globalErrorCallback: ErrorCallback?
|
|
22
|
+
|
|
23
|
+
private var fileHandle: FileHandle?
|
|
24
|
+
|
|
25
|
+
func generateCacheFilePath(extension ext: String) -> String {
|
|
26
|
+
let uuid = UUID()
|
|
27
|
+
let imageNameWithoutExtension = uuid.uuidString
|
|
28
|
+
let imageName = imageNameWithoutExtension + "." + ext
|
|
29
|
+
let filePath = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(imageName).path
|
|
30
|
+
return filePath
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
static func downloadFileAndSaveToCache(_ fileUrl: String, uuid: String,progressDivider: Int, completion: @escaping (String) -> Void) {
|
|
34
|
+
let downloader = Downloader()
|
|
35
|
+
|
|
36
|
+
downloader.downloadFile(fromUrl: fileUrl,progressDivider: progressDivider) { filePath in
|
|
37
|
+
MediaCache.addCompletedImagePath(filePath)
|
|
38
|
+
print("download completed file path: \(filePath)")
|
|
39
|
+
completion(filePath)
|
|
40
|
+
} progressCallback: { progress in
|
|
41
|
+
EventEmitterHandler.emitDownloadProgress(progress, uuid: uuid)
|
|
42
|
+
} errorCallback: { error in
|
|
43
|
+
print("error downloadFile", error)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
func downloadFile(fromUrl: String, progressDivider: Int, downloadCompleteCallback: @escaping DownloadCompleteCallback, progressCallback: @escaping ProgressCallback, errorCallback: @escaping ErrorCallback) -> String? {
|
|
48
|
+
globalProgressCallback = progressCallback
|
|
49
|
+
globalDownloadCompleteCallback = downloadCompleteCallback
|
|
50
|
+
globalErrorCallback = errorCallback
|
|
51
|
+
self.progressDivider=progressDivider
|
|
52
|
+
|
|
53
|
+
lastProgressEmitTimestamp = 0
|
|
54
|
+
bytesWritten = 0
|
|
55
|
+
|
|
56
|
+
guard let url = URL(string: fromUrl) else {
|
|
57
|
+
let error = NSError(domain: "Downloader", code: NSURLErrorBadURL, userInfo: [NSLocalizedDescriptionKey: "Invalid URL"])
|
|
58
|
+
globalErrorCallback?(error)
|
|
59
|
+
return nil
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
let fileExtension = url.pathExtension
|
|
63
|
+
toFile = generateCacheFilePath(extension: fileExtension)
|
|
64
|
+
|
|
65
|
+
if FileManager.default.fileExists(atPath: toFile!) {
|
|
66
|
+
fileHandle = FileHandle(forWritingAtPath: toFile!)
|
|
67
|
+
|
|
68
|
+
if fileHandle == nil {
|
|
69
|
+
let error = NSError(domain: "Downloader", code: NSURLErrorFileDoesNotExist, userInfo: [NSLocalizedDescriptionKey: "Failed to write target file at path: \(toFile!)"])
|
|
70
|
+
globalErrorCallback?(error)
|
|
71
|
+
return nil
|
|
72
|
+
} else {
|
|
73
|
+
fileHandle?.closeFile()
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
let config = URLSessionConfiguration.default
|
|
78
|
+
session = URLSession(configuration: config, delegate: self, delegateQueue: nil)
|
|
79
|
+
task = session?.downloadTask(with: url)
|
|
80
|
+
task?.resume()
|
|
81
|
+
|
|
82
|
+
return nil
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
|
|
86
|
+
guard let httpResponse = downloadTask.response as? HTTPURLResponse else { return }
|
|
87
|
+
|
|
88
|
+
statusCode = NSNumber(value: httpResponse.statusCode)
|
|
89
|
+
contentLength = NSNumber(value: httpResponse.expectedContentLength)
|
|
90
|
+
|
|
91
|
+
if statusCode?.intValue == 200 {
|
|
92
|
+
self.bytesWritten = NSNumber(value: totalBytesWritten)
|
|
93
|
+
|
|
94
|
+
let doubleBytesWritten = Double(truncating: self.bytesWritten!)
|
|
95
|
+
let doubleContentLength = Double(truncating: contentLength!)
|
|
96
|
+
let doublePercents = doubleBytesWritten / doubleContentLength * 100
|
|
97
|
+
let progress = NSNumber(value: floor(doublePercents))
|
|
98
|
+
|
|
99
|
+
if self.progressDivider==0||progress.intValue % self.progressDivider == 0 {
|
|
100
|
+
if (progress != lastProgressValue) || (bytesWritten == contentLength as! Int64) {
|
|
101
|
+
lastProgressValue = progress
|
|
102
|
+
let progressPercentage = NSNumber(value: Double(truncating: self.bytesWritten!) / Double(truncating: contentLength!))
|
|
103
|
+
globalProgressCallback?(progressPercentage)
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
|
|
110
|
+
guard let httpResponse = downloadTask.response as? HTTPURLResponse else { return }
|
|
111
|
+
|
|
112
|
+
if statusCode == nil {
|
|
113
|
+
statusCode = NSNumber(value: httpResponse.statusCode)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
let destURL = URL(fileURLWithPath: toFile!)
|
|
117
|
+
let fm = FileManager.default
|
|
118
|
+
|
|
119
|
+
do {
|
|
120
|
+
if statusCode!.intValue >= 200 && statusCode!.intValue < 300 {
|
|
121
|
+
do {
|
|
122
|
+
try fm.removeItem(at: destURL) // Remove file at destination path, if it exists
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
print("unable to remove item \(error)")
|
|
126
|
+
}
|
|
127
|
+
try fm.moveItem(at: location, to: destURL)
|
|
128
|
+
bytesWritten = NSNumber(value: try fm.attributesOfItem(atPath: toFile!)[.size] as! Int64)
|
|
129
|
+
}
|
|
130
|
+
} catch {
|
|
131
|
+
print("Downloader: Unable to move tempfile to destination. \(error)")
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Manually flush and invalidate the session to free up space
|
|
135
|
+
if session != nil {
|
|
136
|
+
session.flush(completionHandler: {
|
|
137
|
+
session.finishTasksAndInvalidate()
|
|
138
|
+
})
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
let fileURL = URL(fileURLWithPath: toFile!)
|
|
142
|
+
globalDownloadCompleteCallback?(fileURL.absoluteString)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
|
|
146
|
+
if let error = error {
|
|
147
|
+
print("Downloader: didCompleteWithError \(error), \(error.localizedDescription)")
|
|
148
|
+
if error._code != NSURLErrorCancelled {
|
|
149
|
+
resumeData = (error as NSError).userInfo[NSURLSessionDownloadTaskResumeData] as? Data
|
|
150
|
+
|
|
151
|
+
if resumeData == nil {
|
|
152
|
+
globalErrorCallback?(error)
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
//
|
|
2
|
+
// EventEmitterHandler.swift
|
|
3
|
+
// react-native-compressor
|
|
4
|
+
//
|
|
5
|
+
// Created by Numan on 09/09/2023.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
|
|
10
|
+
class EventEmitterHandler {
|
|
11
|
+
static var sharedCompressorObject: Any!
|
|
12
|
+
static var hasListener: Bool=false
|
|
13
|
+
|
|
14
|
+
static func initCompressorInstance(_ object: Any) {
|
|
15
|
+
sharedCompressorObject = object
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
static func stopObserving() -> Void {
|
|
20
|
+
hasListener = false
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static func startObserving() -> Void {
|
|
24
|
+
hasListener = true
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
static func emitDownloadProgress(_ progress: NSNumber, uuid: String) {
|
|
28
|
+
var params = [String: Any]()
|
|
29
|
+
var data = [String: Any]()
|
|
30
|
+
params["uuid"] = uuid
|
|
31
|
+
data["progress"] = progress
|
|
32
|
+
params["data"] = data
|
|
33
|
+
|
|
34
|
+
(sharedCompressorObject as AnyObject).sendEvent(withName: "downloadProgress", body: params)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
static func emitVideoCompressProgress(_ progress: Float, uuid: String) {
|
|
38
|
+
if(self.hasListener){
|
|
39
|
+
(sharedCompressorObject as AnyObject).sendEvent(withName: "videoCompressProgress", body: ["uuid": uuid, "data": ["progress": progress]])
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
static func emituploadProgress(_ uuid: String, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
|
|
44
|
+
if(self.hasListener){
|
|
45
|
+
(sharedCompressorObject as AnyObject).sendEvent(withName: "uploadProgress", body: ["uuid": uuid, "data": ["written": totalBytesSent, "total": totalBytesExpectedToSend]])
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
static func emitBackgroundTaskExpired(_ backgroundTaskId:UIBackgroundTaskIdentifier) {
|
|
50
|
+
if(self.hasListener){
|
|
51
|
+
(sharedCompressorObject as AnyObject).sendEvent(withName: "backgroundTaskExpired", body: ["backgroundTaskId": backgroundTaskId])
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
class MediaCache {
|
|
4
|
+
static var completedImagePaths: [String] = []
|
|
5
|
+
|
|
6
|
+
class func addCompletedImagePath(_ imagePath: String) {
|
|
7
|
+
if !imagePath.isEmpty {
|
|
8
|
+
completedImagePaths.append(imagePath)
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
class func removeCompletedImagePath(_ imagePath: String) {
|
|
13
|
+
if !imagePath.isEmpty {
|
|
14
|
+
if let index = completedImagePaths.firstIndex(of: imagePath) {
|
|
15
|
+
completedImagePaths.remove(at: index)
|
|
16
|
+
if let fileURL = URL(string: imagePath) {
|
|
17
|
+
let fileSystemPath = fileURL.path
|
|
18
|
+
|
|
19
|
+
let fileManager = FileManager.default
|
|
20
|
+
do {
|
|
21
|
+
if fileManager.fileExists(atPath: fileSystemPath) {
|
|
22
|
+
try fileManager.removeItem(atPath: fileSystemPath)
|
|
23
|
+
}
|
|
24
|
+
} catch {
|
|
25
|
+
print("Error deleting image at path: \(fileSystemPath)")
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
class func cleanupCache() {
|
|
33
|
+
let fileManager = FileManager.default
|
|
34
|
+
if let cacheDirectory = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).first {
|
|
35
|
+
for imagePath in completedImagePaths {
|
|
36
|
+
let absoluteImagePath = (cacheDirectory as NSString).appendingPathComponent(imagePath)
|
|
37
|
+
do {
|
|
38
|
+
if fileManager.fileExists(atPath: absoluteImagePath) {
|
|
39
|
+
try fileManager.removeItem(atPath: absoluteImagePath)
|
|
40
|
+
}
|
|
41
|
+
} catch {
|
|
42
|
+
print("Error deleting image at path: \(absoluteImagePath)")
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
completedImagePaths.removeAll()
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Uploader.swift
|
|
3
|
+
// react-native-compressor
|
|
4
|
+
//
|
|
5
|
+
// Created by Numan on 10/09/2023.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
|
|
10
|
+
struct UploadError: Error {
|
|
11
|
+
private let message: String
|
|
12
|
+
|
|
13
|
+
var localizedDescription: String {
|
|
14
|
+
return message
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
init(message: String) {
|
|
18
|
+
self.message = message
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
class Uploader : NSObject, URLSessionTaskDelegate{
|
|
23
|
+
var uploadResolvers: [String: RCTPromiseResolveBlock] = [:]
|
|
24
|
+
var uploadRejectors: [String: RCTPromiseRejectBlock] = [:]
|
|
25
|
+
|
|
26
|
+
func upload(filePath: String, options: [String: Any], resolve:@escaping RCTPromiseResolveBlock, reject:@escaping RCTPromiseRejectBlock) -> Void {
|
|
27
|
+
let fileUrl = Utils.makeValidUri(filePath: filePath)
|
|
28
|
+
|
|
29
|
+
guard let uuid = options["uuid"] as? String else {
|
|
30
|
+
let uploadError = UploadError(message: "UUID is missing")
|
|
31
|
+
reject("Upload Failed", "UUID is missing", uploadError)
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
guard let remoteUrl = options["url"] as? String else {
|
|
36
|
+
let uploadError = UploadError(message: "url is missing")
|
|
37
|
+
reject("Upload Failed", "url is missing", uploadError)
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
guard let method = options["method"] as? String else {
|
|
42
|
+
let uploadError = UploadError(message: "method is missing")
|
|
43
|
+
reject("Upload Failed", "method is missing", uploadError)
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
guard let file = URL(string: fileUrl) else{
|
|
48
|
+
let uploadError = UploadError(message: "invalid file url")
|
|
49
|
+
reject("Failed", "Upload Failed", uploadError)
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
let headers = options["headers"] as? [String: String] ?? [:]
|
|
54
|
+
|
|
55
|
+
let url = URL(string: remoteUrl)!
|
|
56
|
+
var request = URLRequest(url: url)
|
|
57
|
+
request.httpMethod=method
|
|
58
|
+
for(header, v) in headers{
|
|
59
|
+
request.setValue(v, forHTTPHeaderField: header)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
uploadResolvers[uuid] = resolve
|
|
63
|
+
uploadRejectors[uuid] = reject
|
|
64
|
+
// TODO: ADD Headers
|
|
65
|
+
let config = URLSessionConfiguration.background(withIdentifier: uuid)
|
|
66
|
+
let session = URLSession(configuration: config, delegate: self, delegateQueue: nil)
|
|
67
|
+
let task = session.uploadTask(with: request, fromFile: file)
|
|
68
|
+
task.resume()
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
|
|
72
|
+
guard let uuid = session.configuration.identifier else {return}
|
|
73
|
+
guard let reject = uploadRejectors[uuid] else{return}
|
|
74
|
+
guard let resolve = uploadResolvers[uuid] else{return}
|
|
75
|
+
guard error == nil else {
|
|
76
|
+
reject("failed", "Upload Failed", error)
|
|
77
|
+
uploadRejectors[uuid] = nil
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
guard let response = task.response as? HTTPURLResponse else {
|
|
82
|
+
let uploadError = UploadError(message: "Response is not defined")
|
|
83
|
+
reject("failed", "Upload Failed", uploadError)
|
|
84
|
+
uploadRejectors[uuid] = nil
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
let result: [String : Any] = ["status": response.statusCode, "headers": response.allHeaderFields, "body": ""]
|
|
89
|
+
|
|
90
|
+
resolve(result)
|
|
91
|
+
uploadResolvers[uuid] = nil
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64)
|
|
95
|
+
{
|
|
96
|
+
guard let uuid = session.configuration.identifier else {return}
|
|
97
|
+
EventEmitterHandler.emituploadProgress(uuid,totalBytesSent: totalBytesSent,totalBytesExpectedToSend: totalBytesExpectedToSend)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Utils.swift
|
|
3
|
+
// react-native-compressor
|
|
4
|
+
//
|
|
5
|
+
// Created by Numan on 10/09/2023.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
|
|
10
|
+
class Utils {
|
|
11
|
+
static func generateCacheFilePath(_ extension: String) -> String {
|
|
12
|
+
let uuid = UUID()
|
|
13
|
+
let imageNameWithoutExtension = uuid.uuidString
|
|
14
|
+
let imageName = imageNameWithoutExtension + "." + `extension`
|
|
15
|
+
let filePath = (NSTemporaryDirectory() as NSString).appendingPathComponent(imageName)
|
|
16
|
+
return filePath
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static func makeValidUri(filePath: String) -> String {
|
|
20
|
+
let fileWithUrl = URL(fileURLWithPath: filePath)
|
|
21
|
+
let absoluteUrl = fileWithUrl.deletingLastPathComponent()
|
|
22
|
+
let fileUrl = "file://\(absoluteUrl.path)/\(fileWithUrl.lastPathComponent)"
|
|
23
|
+
return fileUrl;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
static func getFileSize(from urlString: String, completion: @escaping (NSNumber?, Error?) -> Void) {
|
|
27
|
+
if let url = URL(string: urlString) {
|
|
28
|
+
var request = URLRequest(url: url)
|
|
29
|
+
request.httpMethod = "HEAD"
|
|
30
|
+
|
|
31
|
+
let session = URLSession.shared
|
|
32
|
+
let task = session.dataTask(with: request) { data, response, error in
|
|
33
|
+
if let error = error {
|
|
34
|
+
completion(nil, error)
|
|
35
|
+
} else if let httpResponse = response as? HTTPURLResponse {
|
|
36
|
+
let contentLength = NSNumber(value: httpResponse.expectedContentLength)
|
|
37
|
+
completion(contentLength, nil)
|
|
38
|
+
} else {
|
|
39
|
+
let error = NSError(domain: "FileDownloadError", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid response."])
|
|
40
|
+
completion(nil, error)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
task.resume()
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
static func getFileSize(_ filePath: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
49
|
+
do {
|
|
50
|
+
if filePath.hasPrefix("http://") || filePath.hasPrefix("https://") {
|
|
51
|
+
getFileSize(from: filePath) { fileSize, error in
|
|
52
|
+
if let error = error {
|
|
53
|
+
print("Error: \(error.localizedDescription)")
|
|
54
|
+
reject(String(error._code), error.localizedDescription, error)
|
|
55
|
+
} else if let fileSize = fileSize {
|
|
56
|
+
print("File size: \(fileSize)")
|
|
57
|
+
resolve(fileSize.stringValue)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
} else {
|
|
61
|
+
var filePath = filePath
|
|
62
|
+
if filePath.hasPrefix("file://") {
|
|
63
|
+
filePath = filePath.replacingOccurrences(of: "file://", with: "")
|
|
64
|
+
}
|
|
65
|
+
let fileManager = FileManager.default
|
|
66
|
+
var isDir: ObjCBool = false
|
|
67
|
+
if !fileManager.fileExists(atPath: filePath, isDirectory: &isDir) || isDir.boolValue {
|
|
68
|
+
let err = NSError(domain: "file not found", code: -15, userInfo: nil)
|
|
69
|
+
reject(String(err.code), err.localizedDescription, err)
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
if let attrs = try? fileManager.attributesOfItem(atPath: filePath),
|
|
73
|
+
let fileSize = attrs[.size] as? UInt64 {
|
|
74
|
+
let fileSizeString = String(fileSize)
|
|
75
|
+
resolve(fileSizeString)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
} catch {
|
|
79
|
+
reject(error.localizedDescription, error.localizedDescription, nil)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
static func getRealPath(_ path: String, type: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
85
|
+
do {
|
|
86
|
+
if type == "video" {
|
|
87
|
+
VideoCompressor.getAbsoluteVideoPath(path, options: [:]) { absoluteImagePath in
|
|
88
|
+
resolve(absoluteImagePath)
|
|
89
|
+
}
|
|
90
|
+
} else {
|
|
91
|
+
let options = ImageCompressorOptions.fromDictionary([:])
|
|
92
|
+
ImageCompressor.getAbsoluteImagePath(path, options: options) { absoluteImagePath in
|
|
93
|
+
resolve(absoluteImagePath)
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
} catch {
|
|
97
|
+
reject(error.localizedDescription, error.localizedDescription, nil)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
static func generateFilePath(_ _extension: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
102
|
+
do {
|
|
103
|
+
let outputUri = generateCacheFilePath(_extension)
|
|
104
|
+
resolve(outputUri)
|
|
105
|
+
} catch {
|
|
106
|
+
reject(error.localizedDescription, error.localizedDescription, nil)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
}
|