diff --git a/CHANGELOG.md b/CHANGELOG.md index 9eb5955..e58d836 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.1.0] + +### 21-01-2026 + +### Feature + +- Allow reading parts of a file with `offset` and `length`. + ## [1.0.3] ### 13-01-2026 diff --git a/package.json b/package.json index e6d6a64..ad03548 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "com.outsystems.plugins.filesystem", - "version": "1.0.3", + "version": "1.1.0", "private": true, "dependencies": {}, "scripts": { diff --git a/packages/cordova-plugin/README.md b/packages/cordova-plugin/README.md index 2911581..467c992 100644 --- a/packages/cordova-plugin/README.md +++ b/packages/cordova-plugin/README.md @@ -266,11 +266,13 @@ Copy a file or directory #### ReadFileOptions -| Prop | Type | Description | Since | -| --------------- | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- | -| **`path`** | string | The path of the file to read | 1.0.0 | -| **`directory`** | Directory | The `Directory` to read the file from | 1.0.0 | -| **`encoding`** | Encoding | The encoding to read the file in, if not provided, data is read as binary and returned as base64 encoded. Pass Encoding.UTF8 to read data as string | 1.0.0 | +| Prop | Type | Description | Default | Since | +| --------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------- | ----- | +| **`path`** | string | The path of the file to read | | 1.0.0 | +| **`directory`** | Directory | The `Directory` to read the file from | | 1.0.0 | +| **`encoding`** | Encoding | The encoding to read the file in, if not provided, data is read as binary and returned as base64 encoded. Pass Encoding.UTF8 to read data as string | | 1.0.0 | +| **`offset`** | number | The offset to start reading the file from, in bytes. Native only (not available in web). Can be used in conjunction with length to partially read files. | 0 | 1.1.0 | +| **`length`** | number | The length of data to read, in bytes. Any non-positive value means to read to the end of the file. Native only (not available in web). Can be used in conjunction with offset to partially read files. | -1 | 1.1.0 | #### ReadFileInChunksOptions diff --git a/packages/cordova-plugin/android/OSFileErrors.kt b/packages/cordova-plugin/android/OSFileErrors.kt index 1f4bad8..4677c83 100644 --- a/packages/cordova-plugin/android/OSFileErrors.kt +++ b/packages/cordova-plugin/android/OSFileErrors.kt @@ -97,5 +97,7 @@ fun Throwable.toFilesystemError(method: OSFileMethod): OSFileErrors.ErrorInfo = is IONFILEExceptions.CopyRenameFailed.NoParentDirectory -> OSFileErrors.missingParentDirectories + is IllegalArgumentException -> OSFileErrors.invalidInputMethod(method.methodName) + else -> OSFileErrors.operationFailed(method.methodName, this.localizedMessage ?: "") } \ No newline at end of file diff --git a/packages/cordova-plugin/android/OSFileOptions.kt b/packages/cordova-plugin/android/OSFileOptions.kt index 817f218..367a45c 100644 --- a/packages/cordova-plugin/android/OSFileOptions.kt +++ b/packages/cordova-plugin/android/OSFileOptions.kt @@ -1,5 +1,6 @@ package com.outsystems.plugins.file +import io.ionic.libs.ionfilesystemlib.model.IONFILEConstants import io.ionic.libs.ionfilesystemlib.model.IONFILEEncoding import io.ionic.libs.ionfilesystemlib.model.IONFILEFolderType import io.ionic.libs.ionfilesystemlib.model.IONFILEReadInChunksOptions @@ -13,6 +14,8 @@ import org.json.JSONObject private const val INPUT_PATH = "path" private const val INPUT_DIRECTORY = "directory" private const val INPUT_ENCODING = "encoding" +private const val INPUT_OFFSET = "offset" +private const val INPUT_LENGTH = "length" private const val INPUT_CHUNK_SIZE = "chunkSize" private const val INPUT_DATA = "data" private const val INPUT_RECURSIVE = "recursive" @@ -53,7 +56,15 @@ internal fun JSONObject.getReadFileOptions(): OSFileReadOptions? { try { val uri = getSingleIONFILEUri() ?: return null val encoding = IONFILEEncoding.fromEncodingName(optString(INPUT_ENCODING)) - return OSFileReadOptions(uri = uri, options = IONFILEReadOptions(encoding)) + val offsetAndLength = getOffsetAndLength() + return OSFileReadOptions( + uri = uri, + options = IONFILEReadOptions( + encoding, + offset = offsetAndLength.first, + length = offsetAndLength.second + ) + ) } catch (ex: JSONException) { return null } @@ -67,9 +78,16 @@ internal fun JSONObject.getReadFileInChunksOptions(): OSFileReadInChunksOptions? val uri = getSingleIONFILEUri() ?: return null val encoding = IONFILEEncoding.fromEncodingName(optString(INPUT_ENCODING)) val chunkSize = getInt(INPUT_CHUNK_SIZE).takeIf { it > 0 } ?: return null + val offsetAndLength = getOffsetAndLength() return OSFileReadInChunksOptions( uri = uri, - options = IONFILEReadInChunksOptions(encoding = encoding, chunkSize = chunkSize) + options = + IONFILEReadInChunksOptions( + encoding = encoding, + chunkSize = chunkSize, + offset = offsetAndLength.first, + length = offsetAndLength.second + ) ) } catch (ex: JSONException) { return null @@ -146,6 +164,11 @@ internal fun JSONObject.getSingleIONFILEUri(): IONFILEUri.Unresolved? { } } +private fun JSONObject.getOffsetAndLength(): Pair = Pair( + optInt(INPUT_OFFSET, 0).takeIf { it >= 0 } ?: 0, + optInt(INPUT_LENGTH, -1).takeIf { it > 0 } ?: IONFILEConstants.LENGTH_READ_TIL_EOF +) + private fun unresolvedUri(path: String, directoryAlias: String?) = IONFILEUri.Unresolved( parentFolder = IONFILEFolderType.fromStringAlias(directoryAlias), uriPath = path diff --git a/packages/cordova-plugin/android/build.gradle b/packages/cordova-plugin/android/build.gradle index c6bca92..f4baf72 100644 --- a/packages/cordova-plugin/android/build.gradle +++ b/packages/cordova-plugin/android/build.gradle @@ -17,7 +17,7 @@ allprojects { } dependencies{ - implementation("io.ionic.libs:ionfilesystem-android:1.0.0@aar") + implementation("io.ionic.libs:ionfilesystem-android:1.1.0@aar") implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3' diff --git a/packages/cordova-plugin/android/libs/IONFilesystemLib-debug.aar b/packages/cordova-plugin/android/libs/IONFilesystemLib-debug.aar deleted file mode 100644 index 45d90b9..0000000 Binary files a/packages/cordova-plugin/android/libs/IONFilesystemLib-debug.aar and /dev/null differ diff --git a/packages/cordova-plugin/dist/definitions.d.ts b/packages/cordova-plugin/dist/definitions.d.ts index 7db4f87..fccd2a7 100644 --- a/packages/cordova-plugin/dist/definitions.d.ts +++ b/packages/cordova-plugin/dist/definitions.d.ts @@ -198,6 +198,25 @@ export interface ReadFileOptions { * @since 1.0.0 */ encoding?: Encoding; + /** + * The offset to start reading the file from, in bytes. + * Native only (not available in web). + * Can be used in conjunction with length to partially read files. + * + * @since 1.1.0 + * @default 0 + */ + offset?: number; + /** + * The length of data to read, in bytes. + * Any non-positive value means to read to the end of the file. + * Native only (not available in web). + * Can be used in conjunction with offset to partially read files. + * + * @since 1.1.0 + * @default -1 + */ + length?: number; } export interface ReadFileInChunksOptions extends ReadFileOptions { /** diff --git a/packages/cordova-plugin/ios/OSFileOperation.swift b/packages/cordova-plugin/ios/OSFileOperation.swift index 7711a5a..767b8b1 100644 --- a/packages/cordova-plugin/ios/OSFileOperation.swift +++ b/packages/cordova-plugin/ios/OSFileOperation.swift @@ -3,8 +3,8 @@ import IONFilesystemLib enum OSFileOperation { // Read Operations - case readFile(url: URL, encoding: IONFILEEncoding) - case readFileInChunks(url: URL, encoding: IONFILEEncoding, chunkSize: Int) + case readFile(url: URL, encoding: IONFILEEncoding, offset: Int, length: Int) + case readFileInChunks(url: URL, encoding: IONFILEEncoding, chunkSize: Int, offset: Int, length: Int) case readdir(url: URL) case stat(url: URL) case getUri(url: URL) diff --git a/packages/cordova-plugin/ios/OSFileOperationExecutor.swift b/packages/cordova-plugin/ios/OSFileOperationExecutor.swift index bb92ca5..4aa43bc 100644 --- a/packages/cordova-plugin/ios/OSFileOperationExecutor.swift +++ b/packages/cordova-plugin/ios/OSFileOperationExecutor.swift @@ -19,11 +19,11 @@ class OSFileOperationExecutor { var resultData: PluginResultData? switch operation { - case .readFile(let url, let encoding): - let fullData = try service.readEntireFile(atURL: url, withEncoding: encoding).textValue + case .readFile(let url, let encoding, let offset, let length): + let fullData = try service.readEntireFile(atURL: url, withEncoding: encoding, andOffset: offset, andLength: length).textValue resultData = [OSFileConstants.ResultDataKey.data: fullData] - case .readFileInChunks(let url, let encoding, let chunkSize): - try processFileInChunks(at: url, withEncoding: encoding, chunkSize: chunkSize, for: operation, command) + case .readFileInChunks(let url, let encoding, let chunkSize, let offset, let length): + try processFileInChunks(at: url, withEncoding: encoding, chunkSize: chunkSize, offset: offset, length: length, for: operation, command) return case .write(let url, let encodingMapper, let recursive): try service.saveFile(atURL: url, withEncodingAndData: encodingMapper, includeIntermediateDirectories: recursive) @@ -61,9 +61,9 @@ class OSFileOperationExecutor { } private extension OSFileOperationExecutor { - func processFileInChunks(at url: URL, withEncoding encoding: IONFILEEncoding, chunkSize: Int, for operation: OSFileOperation, _ command: CDVInvokedUrlCommand) throws { + func processFileInChunks(at url: URL, withEncoding encoding: IONFILEEncoding, chunkSize: Int, offset: Int, length: Int, for operation: OSFileOperation, _ command: CDVInvokedUrlCommand) throws { let chunkSizeToUse = chunkSizeToUse(basedOn: chunkSize, and: encoding) - try service.readFileInChunks(atURL: url, withEncoding: encoding, andChunkSize: chunkSizeToUse) + try service.readFileInChunks(atURL: url, withEncoding: encoding, andChunkSize: chunkSizeToUse, andOffset: offset, andLength: length) .sink(receiveCompletion: { completion in switch completion { case .finished: @@ -87,8 +87,8 @@ private extension OSFileOperationExecutor { var path = "" var method: OSFileMethod = OSFileMethod.getUri switch operation { - case .readFile(let url, _): path = url.absoluteString; method = .readFile - case .readFileInChunks(let url, _, _): path = url.absoluteString; method = .readFileInChunks + case .readFile(let url, _, _, _): path = url.absoluteString; method = .readFile + case .readFileInChunks(let url, _, _, _, _): path = url.absoluteString; method = .readFileInChunks case .write(let url, _, _): path = url.absoluteString; method = .writeFile case .append(let url, _, _): path = url.absoluteString; method = .appendFile case .delete(let url): path = url.absoluteString; method = .deleteFile diff --git a/packages/cordova-plugin/ios/OSFilePlugin.swift b/packages/cordova-plugin/ios/OSFilePlugin.swift index df51025..b414078 100644 --- a/packages/cordova-plugin/ios/OSFilePlugin.swift +++ b/packages/cordova-plugin/ios/OSFilePlugin.swift @@ -24,7 +24,7 @@ private extension OSFilePlugin { } performSinglePathOperation(command, options) { - .readFile(url: $0, encoding: options.encoding) + .readFile(url: $0, encoding: options.encoding, offset: options.offset, length: options.length) } } @@ -35,7 +35,7 @@ private extension OSFilePlugin { } performSinglePathOperation(command, options) { - .readFileInChunks(url: $0, encoding: options.encoding, chunkSize: options.chunkSize) + .readFileInChunks(url: $0, encoding: options.encoding, chunkSize: options.chunkSize, offset: options.offset, length: options.length) } } diff --git a/packages/cordova-plugin/ios/OSSinglePathFileOptions.swift b/packages/cordova-plugin/ios/OSSinglePathFileOptions.swift index a7284ac..1fec840 100644 --- a/packages/cordova-plugin/ios/OSSinglePathFileOptions.swift +++ b/packages/cordova-plugin/ios/OSSinglePathFileOptions.swift @@ -41,9 +41,13 @@ class IONSinglePathRecursiveFileOptions: OSSinglePathFileOptions { class IONReadFileOptions: OSSinglePathFileOptions { let encoding: IONFILEEncoding + let offset: Int + let length: Int enum CodingKeys: CodingKey { case encoding + case offset + case length } required init(from decoder: any Decoder) throws { @@ -51,6 +55,16 @@ class IONReadFileOptions: OSSinglePathFileOptions { let encodingText = try container.decodeIfPresent(String.self, forKey: .encoding) encoding = .create(from: encodingText) + if let decodedOffset = try container.decodeIfPresent(Int.self, forKey: .offset) { + offset = decodedOffset + } else { + offset = 0 + } + if let decodedLength = try container.decodeIfPresent(Int.self, forKey: .length) { + length = decodedLength + } else { + length = -1 + } try super.init(from: decoder) } diff --git a/packages/cordova-plugin/package.json b/packages/cordova-plugin/package.json index 309f29c..e965202 100644 --- a/packages/cordova-plugin/package.json +++ b/packages/cordova-plugin/package.json @@ -1,7 +1,7 @@ { "name": "com.outsystems.plugins.filesystem", "displayName": "Filesystem", - "version": "1.0.1", + "version": "1.1.0", "description": "Filesystem plugin for Cordova", "scripts": { "lint": "npm run eslint && npm run prettier -- --check", diff --git a/packages/cordova-plugin/src/definitions.ts b/packages/cordova-plugin/src/definitions.ts index 0b8b042..dea0d25 100644 --- a/packages/cordova-plugin/src/definitions.ts +++ b/packages/cordova-plugin/src/definitions.ts @@ -222,6 +222,27 @@ export interface ReadFileOptions { * @since 1.0.0 */ encoding?: Encoding; + + /** + * The offset to start reading the file from, in bytes. + * Native only (not available in web). + * Can be used in conjunction with length to partially read files. + * + * @since 1.1.0 + * @default 0 + */ + offset?: number; + + /** + * The length of data to read, in bytes. + * Any non-positive value means to read to the end of the file. + * Native only (not available in web). + * Can be used in conjunction with offset to partially read files. + * + * @since 1.1.0 + * @default -1 + */ + length?: number; } export interface ReadFileInChunksOptions extends ReadFileOptions { diff --git a/plugin.xml b/plugin.xml index 8819b50..7929d38 100644 --- a/plugin.xml +++ b/plugin.xml @@ -1,5 +1,5 @@ - + OSFilePlugin OutSystems' cordova geolocation plugin OutSystems Inc @@ -60,8 +60,8 @@ - + - + \ No newline at end of file