diff --git a/NitroFs.podspec b/NitroFS.podspec similarity index 93% rename from NitroFs.podspec rename to NitroFS.podspec index 95a854f..db4ad73 100644 --- a/NitroFs.podspec +++ b/NitroFS.podspec @@ -10,7 +10,7 @@ Pod::Spec.new do |s| s.license = package["license"] s.authors = package["author"] - s.platforms = { :ios => min_ios_version_supported, :visionos => 1.0 } + s.platforms = { :ios => min_ios_version_supported } s.source = { :git => "https://github.com/patrickkabwe/react-native-nitro-fs.git", :tag => "#{s.version}" } s.source_files = [ diff --git a/android/src/main/java/com/nitrofs/FileDownloader.kt b/android/src/main/java/com/nitrofs/FileDownloader.kt index 5dafff5..9b9b4a5 100644 --- a/android/src/main/java/com/nitrofs/FileDownloader.kt +++ b/android/src/main/java/com/nitrofs/FileDownloader.kt @@ -1,11 +1,14 @@ package com.nitrofs +import android.util.Log +import com.margelo.nitro.nitrofs.NitroFile import io.ktor.client.HttpClient import io.ktor.client.call.body import io.ktor.client.engine.okhttp.OkHttp import io.ktor.client.plugins.onDownload import io.ktor.client.request.prepareGet import io.ktor.http.HttpMethod +import io.ktor.http.isSuccess import io.ktor.util.cio.writeChannel import io.ktor.utils.io.ByteReadChannel import io.ktor.utils.io.copyAndClose @@ -16,16 +19,18 @@ import java.io.File class FileDownloader { suspend fun downloadFile( serverUrl: String, - fileName: String, destinationPath: String, onProgress: ((Double, Double) -> Unit)? - ) { + ): NitroFile? { + var contentType = "" val outputFile = File(destinationPath) outputFile.parentFile?.mkdirs() + val client = HttpClient(OkHttp) + client.use { it - it.prepareGet("$serverUrl/$fileName") { + it.prepareGet(serverUrl) { method = HttpMethod.Get onDownload { totalBytesSent, contentLength -> if (totalBytesSent > 0 && contentLength != null){ @@ -37,9 +42,20 @@ class FileDownloader { } } }.execute { response -> + Log.d("TAG", "${response.status.isSuccess()} ${response.status.value} $serverUrl") + if (!response.status.isSuccess()) { + throw RuntimeException("HTTP ${response.status.value}: Failed to download file") + } + contentType = response.headers["Content-Type"] ?: "application/octet-stream" val channel: ByteReadChannel = response.body() channel.copyAndClose(outputFile.writeChannel()) } } + + return NitroFile( + name = outputFile.name, + path = outputFile.absolutePath, + mimeType = contentType + ) } } \ No newline at end of file diff --git a/android/src/main/java/com/nitrofs/HybridNitroFS.kt b/android/src/main/java/com/nitrofs/HybridNitroFS.kt index 55684e7..8217512 100755 --- a/android/src/main/java/com/nitrofs/HybridNitroFS.kt +++ b/android/src/main/java/com/nitrofs/HybridNitroFS.kt @@ -127,18 +127,12 @@ class HybridNitroFS: HybridNitroFSSpec() { override fun downloadFile( serverUrl: String, - fileName: String, destinationPath: String, onProgress: ((Double, Double) -> Unit)? ): Promise { return Promise.async(ioScope) { try { - nitroFsImpl.downloadFile(serverUrl, fileName, destinationPath, onProgress) - NitroFile( - name = fileName, - path = destinationPath, - mimeType = "", - ) + nitroFsImpl.downloadFile(serverUrl, destinationPath, onProgress) } catch (e: Exception) { Log.e("NitroFS", "Error downloading file: ${e.message}") throw Error(e) diff --git a/android/src/main/java/com/nitrofs/NitroFSImpl.kt b/android/src/main/java/com/nitrofs/NitroFSImpl.kt index b218a93..9d7cdc2 100644 --- a/android/src/main/java/com/nitrofs/NitroFSImpl.kt +++ b/android/src/main/java/com/nitrofs/NitroFSImpl.kt @@ -92,16 +92,19 @@ class NitroFSImpl(val context: ReactApplicationContext) { suspend fun downloadFile( serverUrl: String, - fileName: String, destinationPath: String, onProgress: ((Double, Double) -> Unit)? - ) { - fileDownloader.downloadFile( + ): NitroFile { + val file = fileDownloader.downloadFile( serverUrl, - fileName, destinationPath, onProgress ) + if (file != null) { + return file + } else { + throw RuntimeException("Failed to download file from: $serverUrl") + } } fun getFileEncoding(encoding: NitroFileEncoding): Charset { diff --git a/example/App.tsx b/example/App.tsx index 4b62f24..50b6588 100644 --- a/example/App.tsx +++ b/example/App.tsx @@ -9,9 +9,9 @@ const uploadURL = Platform.select({ }); const downloadURL = Platform.select({ - ios: 'http://localhost:5100/download', - android: 'http://10.0.2.2:5100/download', - default: 'http://localhost:5100/download', + ios: 'http://localhost:5100/download/dummyfile.txt', + android: 'http://10.0.2.2:5100/download/dummyfile.txt', + default: 'http://localhost:5100/download/dummyfile.txt', }); const fileToUpload = Platform.select({ @@ -119,7 +119,7 @@ function App(): React.JSX.Element { mimeType: 'text/plain', path: fileToUpload, }, - {url: uploadURL, method: 'POST', field: 'file'}, + { url: uploadURL, method: 'POST', field: 'file'}, (uploadedBytes, totalBytes) => { const progress = (uploadedBytes / totalBytes) * 100; setUploadProgress(Math.round(progress)); @@ -140,7 +140,6 @@ function App(): React.JSX.Element { onPress={() => { NitroFS.downloadFile( downloadURL, - 'dummyfile.txt', NitroFS.DOWNLOAD_DIR + '/dummyfile.txt', (downloadedBytes, totalBytes) => { const progress = (downloadedBytes / totalBytes) * 100; diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 2d730d5..3d06266 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -8,7 +8,7 @@ PODS: - hermes-engine (0.78.0): - hermes-engine/Pre-built (= 0.78.0) - hermes-engine/Pre-built (0.78.0) - - NitroFS (0.2.5): + - NitroFS (0.4.2): - DoubleConversion - glog - hermes-engine @@ -1798,7 +1798,7 @@ SPEC CHECKSUMS: fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd glog: eb93e2f488219332457c3c4eafd2738ddc7e80b8 hermes-engine: b417d2b2aee3b89b58e63e23a51e02be91dc876d - NitroFS: 979894cea0ce1469f6baf81d4e755e2209b05749 + NitroFS: 1bb934dabe27fe3c8d7838cb638cc4bb9a40548c NitroModules: 5cc92d3b0baf1124ed8136a015924eea03db912e RCT-Folly: e78785aa9ba2ed998ea4151e314036f6c49e6d82 RCTDeprecation: b2eecf2d60216df56bc5e6be5f063826d3c1ee35 diff --git a/ios/HybridNitroFs.swift b/ios/HybridNitroFs.swift index b05a6fb..1e80840 100755 --- a/ios/HybridNitroFs.swift +++ b/ios/HybridNitroFs.swift @@ -30,7 +30,7 @@ class HybridNitroFS: HybridNitroFSSpec { try self.nitroFSImpl.writeFile(path: filepath, data: data, encoding: encoding) } catch { os_log("Failed to write file content: \(error.localizedDescription)") - throw NitroFSError.nitroFSWriteFailed(message: "Failed to wriote file content to disk") + throw NitroFSError.fileError(message: "Failed to write file content to disk") } } } @@ -41,7 +41,7 @@ class HybridNitroFS: HybridNitroFSSpec { return try self.nitroFSImpl.readFile(path: path, encoding: encoding) } catch { os_log("Failed to read file content: \(error.localizedDescription)") - throw NitroFSError.nitroFSWriteFailed(message: "Failed to write file content to disk") + throw NitroFSError.fileError(message: "Failed to write file content to disk") } } } @@ -52,7 +52,7 @@ class HybridNitroFS: HybridNitroFSSpec { try self.nitroFSImpl.copy(source: srcPath, destination: destPath) } catch { os_log("Failed to copy file content: \(error.localizedDescription)") - throw NitroFSError.nitroFSWriteFailed(message: "Failed to copy file file content to disk") + throw NitroFSError.fileError(message: "Failed to copy file file content to disk") } } } @@ -63,7 +63,7 @@ class HybridNitroFS: HybridNitroFSSpec { try self.nitroFSImpl.copy(source: srcPath, destination: destPath) } catch { os_log("Failed to copy file or directory: \(error.localizedDescription)") - throw NitroFSError.nitroFSWriteFailed(message: "Failed to copy file or directory content to disk") + throw NitroFSError.fileError(message: "Failed to copy file or directory content to disk") } } } @@ -99,7 +99,7 @@ class HybridNitroFS: HybridNitroFSSpec { } catch { os_log("Failed to get stat: \(error.localizedDescription)") - throw NitroFSError.nitroFSInvalidEncoding(message: "Failed to get stat: \(error.localizedDescription)") + throw NitroFSError.encodingError(message: "Failed to get stat: \(error.localizedDescription)") } } } @@ -123,12 +123,11 @@ class HybridNitroFS: HybridNitroFSSpec { } } - func downloadFile(serverUrl: String, fileName: String, destinationPath: String, onProgress: ((Double, Double) -> Void)?) throws -> NitroModules.Promise { + func downloadFile(serverUrl: String, destinationPath: String, onProgress: ((Double, Double) -> Void)?) throws -> NitroModules.Promise { return .async { [unowned self] in do { return try await self.nitroFSImpl.downloadFile( serverUrl: serverUrl, - fileName: fileName, destinationPath: destinationPath, onProgress: onProgress ) diff --git a/ios/NitroFSFileDownloader.swift b/ios/NitroFSFileDownloader.swift index 3436040..55a1110 100644 --- a/ios/NitroFSFileDownloader.swift +++ b/ios/NitroFSFileDownloader.swift @@ -8,8 +8,6 @@ import Foundation final class NitroFSFileDownloader: NSObject { - // MARK: - Properties - private weak var fileManager: FileManager? private var downloadTask: URLSessionDownloadTask? private var onProgress: ((Double, Double) -> Void)? @@ -20,23 +18,20 @@ final class NitroFSFileDownloader: NSObject { self.fileManager = fileManager super.init() } - - // MARK: - Public Methods - + func downloadFile( _ serverUrl: String, - _ fileName: String, _ destinationPath: String, onProgress: ((Double, Double) -> Void)? = nil ) async throws -> NitroFile { guard fileManager != nil else { - throw NitroFSError.nitroFSUnavailable(message: "FileManager is not available") + throw NitroFSError.unavailable(message: "FileManager is not available") } self.onProgress = onProgress self.destinationPath = destinationPath - let request = try makeRequest(serverUrl: serverUrl, fileName: fileName) + let request = try makeRequest(serverUrl: serverUrl) let session: URLSession = { let config = URLSessionConfiguration.default @@ -58,9 +53,9 @@ final class NitroFSFileDownloader: NSObject { // MARK: - Private Methods - private func makeRequest(serverUrl: String, fileName: String) throws -> URLRequest { - guard let encodedFilename = fileName.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed), - let url = URL(string: "\(serverUrl)/\(encodedFilename)") else { + private func makeRequest(serverUrl: String) throws -> URLRequest { + guard let encoded = serverUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed), + let url = URL(string: encoded) else { throw URLError(.badURL) } @@ -76,19 +71,19 @@ final class NitroFSFileDownloader: NSObject { downloadTask: URLSessionDownloadTask ) throws -> NitroFile { guard let fileManager else { - throw NitroFSError.nitroFSUnavailable(message: "FileManager is not available") + throw NitroFSError.unavailable(message: "FileManager is not available") } guard let response = response as? HTTPURLResponse else { - throw NitroFSError.nitroFSDownloadFailed(message: "Invalid response type") + throw NitroFSError.networkError(message: "Invalid response type") } guard (200...299).contains(response.statusCode) else { - throw NitroFSError.nitroFSDownloadFailed(message: "HTTP Error: \(response.statusCode)") + throw NitroFSError.networkError(message: "HTTP Error: \(response.statusCode)") } guard let destinationPath = self.destinationPath else { - throw NitroFSError.nitroFSDownloadFailed(message: "Destination path not set") + throw NitroFSError.networkError(message: "Destination path not set") } let destinationURL = URL(fileURLWithPath: destinationPath) @@ -130,6 +125,7 @@ extension NitroFSFileDownloader: URLSessionDownloadDelegate { continuation.resume(throwing: error) } self.continuation = nil + session.finishTasksAndInvalidate() } func urlSession( @@ -153,6 +149,7 @@ extension NitroFSFileDownloader: URLSessionDownloadDelegate { if let error { continuation?.resume(throwing: error) continuation = nil + session.finishTasksAndInvalidate() } } } diff --git a/ios/NitroFSFileUploader.swift b/ios/NitroFSFileUploader.swift index ba3f0a3..0a88c7b 100644 --- a/ios/NitroFSFileUploader.swift +++ b/ios/NitroFSFileUploader.swift @@ -7,40 +7,166 @@ import Foundation -final class NitroFSFileUploader: NSObject, URLSessionTaskDelegate, URLSessionDataDelegate { +final class NitroFSFileUploader: NSObject, URLSessionDataDelegate { weak var fileManager: FileManager? private var onProgress: ((Double, Double) -> Void)? - + init(fileManager: FileManager) { super.init() self.fileManager = fileManager } - + func uploadFile( file: NitroFile, uploadOptions: NitroUploadOptions, onProgress: ((Double, Double) -> Void)? = nil ) async throws { self.onProgress = onProgress + guard let uploadURL = URL(string: uploadOptions.url) else { - throw NetworkError.invalidURL(message: "Invalid URL") + throw NitroFSError.networkError(message: "Invalid URL") } - + + let fieldName = uploadOptions.field ?? "file" + let boundary = UUID().uuidString let fileURL = URL(fileURLWithPath: file.path) - _ = uploadOptions.field ?? "file" - //TODO: Implement upload file - - return try await withCheckedThrowingContinuation { continuation in - continuation.resume() + // Create multipart file body on disk + let multipartFile = try createMultipartBodyFile( + fileURL: fileURL, + fieldName: fieldName, + boundary: boundary + ) + + var request = URLRequest(url: uploadURL) + request.httpMethod = "POST" + request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type") + + return try await withCheckedThrowingContinuation { [weak self] continuation in + let session = URLSession(configuration: .default, delegate: self, delegateQueue: nil) + + let task = session.uploadTask(with: request, fromFile: multipartFile) { _, response, error in + defer { + try? FileManager.default.removeItem(at: multipartFile) + session.finishTasksAndInvalidate() + } + + if let error = error { + continuation.resume(throwing: error) + return + } + + guard let httpResponse = response as? HTTPURLResponse, + (200...299).contains(httpResponse.statusCode) else { + continuation.resume(throwing: NitroFSError.networkError(message: "Invalid server response")) + return + } + + continuation.resume() + } + + task.resume() + } + } +} + +// MARK: - Helpers + +extension NitroFSFileUploader { + private func createMultipartBodyFile( + fileURL: URL, + fieldName: String, + boundary: String + ) throws -> URL { + let tempURL = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString) + + guard let output = OutputStream(url: tempURL, append: false) else { + throw NitroFSError.encodingError(message: "Failed to create output stream") } + + output.open() + defer { output.close() } + + // Write multipart headers with proper CRLF line endings + let header = """ + --\(boundary)\r\n\ + Content-Disposition: form-data; name="\(fieldName)"; filename="\(fileURL.lastPathComponent)"\r\n\ + Content-Type: application/octet-stream\r\n\ + \r\n + """ + try output.write(header) + + // Stream file content efficiently + try streamFileContent(from: fileURL, to: output) + + // Write multipart footer + let footer = "\r\n--\(boundary)--\r\n" + try output.write(footer) + + return tempURL } - // MARK: - URLSession Delegate (optional for progress) - func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, + private func streamFileContent(from fileURL: URL, to output: OutputStream) throws { + guard let input = InputStream(url: fileURL) else { + throw NitroFSError.fileError(message: "Could not read file from disk") + } + + input.open() + defer { input.close() } + + let bufferSize = 64 * 1024 + var buffer = [UInt8](repeating: 0, count: bufferSize) + + while input.hasBytesAvailable { + let bytesRead = input.read(&buffer, maxLength: bufferSize) + + if bytesRead > 0 { + let bytesWritten = output.write(buffer, maxLength: bytesRead) + if bytesWritten != bytesRead { + throw NitroFSError.encodingError(message: "Failed to write file data to output stream") + } + } else if bytesRead < 0 { + throw NitroFSError.fileError(message: "Error reading file data") + } + } + } +} + + +// MARK: - URLSessionTaskDelegate +extension NitroFSFileUploader: URLSessionTaskDelegate { + func urlSession(_ _: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) { DispatchQueue.main.async { - self.onProgress?( Double(totalBytesSent), Double(totalBytesExpectedToSend)) + self.onProgress?(Double(totalBytesSent), Double(totalBytesExpectedToSend)) + } + } +} + +// MARK: - OutputStream Extension + +private extension OutputStream { + func write(_ string: String) throws { + guard let data = string.data(using: .utf8) else { + throw NitroFSError.encodingError(message: "Failed to encode string to UTF-8.") + } + + try data.withUnsafeBytes { buffer in + guard let baseAddress = buffer.baseAddress?.assumingMemoryBound(to: UInt8.self) else { + throw NitroFSError.fileError(message: "Could not get pointer to buffer.") + } + + var bytesRemaining = data.count + var totalBytesWritten = 0 + + while bytesRemaining > 0 { + let written = self.write(baseAddress.advanced(by: totalBytesWritten), maxLength: bytesRemaining) + if written < 0 { + throw NitroFSError.fileError(message: "Failed to write to OutputStream.") + } + bytesRemaining -= written + totalBytesWritten += written + } } } } diff --git a/ios/NitroFSImpl.swift b/ios/NitroFSImpl.swift index 3dc80be..82d37dd 100644 --- a/ios/NitroFSImpl.swift +++ b/ios/NitroFSImpl.swift @@ -27,7 +27,7 @@ class NitroFSImpl { func writeFile(path: String, data: String, encoding: NitroFileEncoding) throws { guard fileManager != nil else { - throw NitroFSError.nitroFSUnavailable(message: "Failed to write file. FileManager is unavailable") + throw NitroFSError.unavailable(message: "Failed to write file. FileManager is unavailable") } try data.write(toFile: path, atomically: true, encoding: getEncoding(nitroEncoding: encoding)) } @@ -44,7 +44,7 @@ class NitroFSImpl { if let string = String(data: chunk, encoding: getEncoding(nitroEncoding: encoding)) { result += string } else { - throw NitroFSError.nitroFSInvalidEncoding(message: "Failed to decode chunk") + throw NitroFSError.encodingError(message: "Failed to decode chunk") } } else { break @@ -56,28 +56,28 @@ class NitroFSImpl { func copy(source: String, destination: String) throws { guard let fileManager else { - throw NitroFSError.nitroFSUnavailable(message: "Failed to copy file. FileManager is unavailable") + throw NitroFSError.unavailable(message: "Failed to copy file. FileManager is unavailable") } try fileManager.copyItem(atPath: source, toPath: destination) } func unlink(path: String) throws { guard let fileManager else { - throw NitroFSError.nitroFSUnavailable(message: "Failed to unlink file. FileManager is unavailable") + throw NitroFSError.unavailable(message: "Failed to unlink file. FileManager is unavailable") } try fileManager.removeItem(atPath: path) } func mkdir(path: String, mode: FileManager.ItemReplacementOptions = []) throws { guard let fileManager else { - throw NitroFSError.nitroFSUnavailable(message: "Failed to mkdir file. FileManager is unavailable") + throw NitroFSError.unavailable(message: "Failed to mkdir file. FileManager is unavailable") } try fileManager.createDirectory(atPath: path, withIntermediateDirectories: true, attributes: nil) } func stat(path: String) throws -> NitroFileStat { guard let fileManager else { - throw NitroFSError.nitroFSUnavailable(message: "Failed to stat file. FileManager is unavailable") + throw NitroFSError.unavailable(message: "Failed to stat file. FileManager is unavailable") } let attributes = try fileManager.attributesOfItem(atPath: path) @@ -108,16 +108,14 @@ class NitroFSImpl { func downloadFile( serverUrl: String, - fileName: String, destinationPath: String, onProgress: ((Double, Double) -> Void)? ) async throws -> NitroFile { guard let fileDownloader else { - throw NitroFSError.nitroFSUnavailable(message: "Failed to stat file. fileDownloader is unavailable") + throw NitroFSError.unavailable(message: "Failed to download file. fileDownloader is unavailable") } return try await fileDownloader.downloadFile( serverUrl, - fileName, destinationPath, onProgress: onProgress ) diff --git a/ios/Utils.swift b/ios/Utils.swift index b07d9c2..4d4d8a2 100644 --- a/ios/Utils.swift +++ b/ios/Utils.swift @@ -21,15 +21,47 @@ struct NitroFSDirs { } enum NitroFSError: Error { - case nitroFSUnavailable(message: String) - case nitroFSWriteFailed(message: String) - case nitroFSInvalidEncoding(message: String) - case nitroFSFileNotFound(message: String) - case nitroFSDownloadFailed(message: String) + case unavailable(message: String) + case fileError(message: String) + case networkError(message: String) + case encodingError(message: String) } -enum NetworkError: Error { - case invalidURL(message: String) - case invalidResponse - case invalidData +extension NitroFSError: LocalizedError { + var errorDescription: String? { + switch self { + case .unavailable(let message), + .fileError(let message), + .networkError(let message), + .encodingError(let message): + return message + } + } +} + + +func generateLargeFile(at path: String, sizeInMB: Int) throws { + let fileURL = URL(fileURLWithPath: path) + let fileSize = sizeInMB * 1024 * 1024 + let chunkSize = 1024 * 1024 + let buffer = [UInt8](repeating: 0x41, count: chunkSize) + + guard let outputStream = OutputStream(url: fileURL, append: false) else { + throw NSError(domain: "FileError", code: 1, userInfo: [NSLocalizedDescriptionKey: "Could not create file"]) + } + + outputStream.open() + defer { outputStream.close() } + + var bytesWritten = 0 + while bytesWritten < fileSize { + let toWrite = min(chunkSize, fileSize - bytesWritten) + let written = outputStream.write(buffer, maxLength: toWrite) + if written <= 0 { + throw NSError(domain: "FileError", code: 2, userInfo: [NSLocalizedDescriptionKey: "Failed to write data"]) + } + bytesWritten += written + } + + print("Generated file at \(path) (\(bytesWritten / 1024 / 1024) MB)") } diff --git a/nitrogen/generated/android/c++/JHybridNitroFSSpec.cpp b/nitrogen/generated/android/c++/JHybridNitroFSSpec.cpp index b0bfd41..f868898 100644 --- a/nitrogen/generated/android/c++/JHybridNitroFSSpec.cpp +++ b/nitrogen/generated/android/c++/JHybridNitroFSSpec.cpp @@ -215,9 +215,9 @@ namespace margelo::nitro::nitrofs { return __promise; }(); } - std::shared_ptr> JHybridNitroFSSpec::downloadFile(const std::string& serverUrl, const std::string& fileName, const std::string& destinationPath, const std::optional>& onProgress) { - static const auto method = javaClassStatic()->getMethod(jni::alias_ref /* serverUrl */, jni::alias_ref /* fileName */, jni::alias_ref /* destinationPath */, jni::alias_ref /* onProgress */)>("downloadFile_cxx"); - auto __result = method(_javaPart, jni::make_jstring(serverUrl), jni::make_jstring(fileName), jni::make_jstring(destinationPath), onProgress.has_value() ? JFunc_void_double_double_cxx::fromCpp(onProgress.value()) : nullptr); + std::shared_ptr> JHybridNitroFSSpec::downloadFile(const std::string& serverUrl, const std::string& destinationPath, const std::optional>& onProgress) { + static const auto method = javaClassStatic()->getMethod(jni::alias_ref /* serverUrl */, jni::alias_ref /* destinationPath */, jni::alias_ref /* onProgress */)>("downloadFile_cxx"); + auto __result = method(_javaPart, jni::make_jstring(serverUrl), jni::make_jstring(destinationPath), onProgress.has_value() ? JFunc_void_double_double_cxx::fromCpp(onProgress.value()) : nullptr); return [&]() { auto __promise = Promise::create(); __result->cthis()->addOnResolvedListener([=](const jni::alias_ref& __boxedResult) { diff --git a/nitrogen/generated/android/c++/JHybridNitroFSSpec.hpp b/nitrogen/generated/android/c++/JHybridNitroFSSpec.hpp index 6595203..57674d0 100644 --- a/nitrogen/generated/android/c++/JHybridNitroFSSpec.hpp +++ b/nitrogen/generated/android/c++/JHybridNitroFSSpec.hpp @@ -63,7 +63,7 @@ namespace margelo::nitro::nitrofs { std::shared_ptr> mkdir(const std::string& path) override; std::shared_ptr> stat(const std::string& path) override; std::shared_ptr> uploadFile(const NitroFile& file, const NitroUploadOptions& uploadOptions, const std::optional>& onProgress) override; - std::shared_ptr> downloadFile(const std::string& serverUrl, const std::string& fileName, const std::string& destinationPath, const std::optional>& onProgress) override; + std::shared_ptr> downloadFile(const std::string& serverUrl, const std::string& destinationPath, const std::optional>& onProgress) override; private: friend HybridBase; diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofs/HybridNitroFSSpec.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofs/HybridNitroFSSpec.kt index d5e5b1a..e1b58a6 100644 --- a/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofs/HybridNitroFSSpec.kt +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrofs/HybridNitroFSSpec.kt @@ -95,12 +95,12 @@ abstract class HybridNitroFSSpec: HybridObject() { return __result } - abstract fun downloadFile(serverUrl: String, fileName: String, destinationPath: String, onProgress: ((downloadedBytes: Double, totalBytes: Double) -> Unit)?): Promise + abstract fun downloadFile(serverUrl: String, destinationPath: String, onProgress: ((downloadedBytes: Double, totalBytes: Double) -> Unit)?): Promise @DoNotStrip @Keep - private fun downloadFile_cxx(serverUrl: String, fileName: String, destinationPath: String, onProgress: Func_void_double_double?): Promise { - val __result = downloadFile(serverUrl, fileName, destinationPath, onProgress?.let { it }) + private fun downloadFile_cxx(serverUrl: String, destinationPath: String, onProgress: Func_void_double_double?): Promise { + val __result = downloadFile(serverUrl, destinationPath, onProgress?.let { it }) return __result } diff --git a/nitrogen/generated/ios/c++/HybridNitroFSSpecSwift.hpp b/nitrogen/generated/ios/c++/HybridNitroFSSpecSwift.hpp index 0c52797..a074fac 100644 --- a/nitrogen/generated/ios/c++/HybridNitroFSSpecSwift.hpp +++ b/nitrogen/generated/ios/c++/HybridNitroFSSpecSwift.hpp @@ -159,8 +159,8 @@ namespace margelo::nitro::nitrofs { auto __value = std::move(__result.value()); return __value; } - inline std::shared_ptr> downloadFile(const std::string& serverUrl, const std::string& fileName, const std::string& destinationPath, const std::optional>& onProgress) override { - auto __result = _swiftPart.downloadFile(serverUrl, fileName, destinationPath, onProgress); + inline std::shared_ptr> downloadFile(const std::string& serverUrl, const std::string& destinationPath, const std::optional>& onProgress) override { + auto __result = _swiftPart.downloadFile(serverUrl, destinationPath, onProgress); if (__result.hasError()) [[unlikely]] { std::rethrow_exception(__result.error()); } diff --git a/nitrogen/generated/ios/swift/HybridNitroFSSpec.swift b/nitrogen/generated/ios/swift/HybridNitroFSSpec.swift index e660078..7ba70b8 100644 --- a/nitrogen/generated/ios/swift/HybridNitroFSSpec.swift +++ b/nitrogen/generated/ios/swift/HybridNitroFSSpec.swift @@ -26,7 +26,7 @@ public protocol HybridNitroFSSpec_protocol: HybridObject { func mkdir(path: String) throws -> Promise func stat(path: String) throws -> Promise func uploadFile(file: NitroFile, uploadOptions: NitroUploadOptions, onProgress: ((_ uploadedBytes: Double, _ totalBytes: Double) -> Void)?) throws -> Promise - func downloadFile(serverUrl: String, fileName: String, destinationPath: String, onProgress: ((_ downloadedBytes: Double, _ totalBytes: Double) -> Void)?) throws -> Promise + func downloadFile(serverUrl: String, destinationPath: String, onProgress: ((_ downloadedBytes: Double, _ totalBytes: Double) -> Void)?) throws -> Promise } /// See ``HybridNitroFSSpec`` diff --git a/nitrogen/generated/ios/swift/HybridNitroFSSpec_cxx.swift b/nitrogen/generated/ios/swift/HybridNitroFSSpec_cxx.swift index 62d27f9..ccfb67b 100644 --- a/nitrogen/generated/ios/swift/HybridNitroFSSpec_cxx.swift +++ b/nitrogen/generated/ios/swift/HybridNitroFSSpec_cxx.swift @@ -309,9 +309,9 @@ public class HybridNitroFSSpec_cxx { } @inline(__always) - public final func downloadFile(serverUrl: std.string, fileName: std.string, destinationPath: std.string, onProgress: bridge.std__optional_std__function_void_double____downloadedBytes_____double____totalBytes______) -> bridge.Result_std__shared_ptr_Promise_NitroFile___ { + public final func downloadFile(serverUrl: std.string, destinationPath: std.string, onProgress: bridge.std__optional_std__function_void_double____downloadedBytes_____double____totalBytes______) -> bridge.Result_std__shared_ptr_Promise_NitroFile___ { do { - let __result = try self.__implementation.downloadFile(serverUrl: String(serverUrl), fileName: String(fileName), destinationPath: String(destinationPath), onProgress: { () -> ((_ downloadedBytes: Double, _ totalBytes: Double) -> Void)? in + let __result = try self.__implementation.downloadFile(serverUrl: String(serverUrl), destinationPath: String(destinationPath), onProgress: { () -> ((_ downloadedBytes: Double, _ totalBytes: Double) -> Void)? in if let __unwrapped = onProgress.value { return { () -> (Double, Double) -> Void in let __wrappedFunction = bridge.wrap_Func_void_double_double(__unwrapped) diff --git a/nitrogen/generated/shared/c++/HybridNitroFSSpec.hpp b/nitrogen/generated/shared/c++/HybridNitroFSSpec.hpp index 94d398b..d26b3fd 100644 --- a/nitrogen/generated/shared/c++/HybridNitroFSSpec.hpp +++ b/nitrogen/generated/shared/c++/HybridNitroFSSpec.hpp @@ -74,7 +74,7 @@ namespace margelo::nitro::nitrofs { virtual std::shared_ptr> mkdir(const std::string& path) = 0; virtual std::shared_ptr> stat(const std::string& path) = 0; virtual std::shared_ptr> uploadFile(const NitroFile& file, const NitroUploadOptions& uploadOptions, const std::optional>& onProgress) = 0; - virtual std::shared_ptr> downloadFile(const std::string& serverUrl, const std::string& fileName, const std::string& destinationPath, const std::optional>& onProgress) = 0; + virtual std::shared_ptr> downloadFile(const std::string& serverUrl, const std::string& destinationPath, const std::optional>& onProgress) = 0; protected: // Hybrid Setup diff --git a/src/specs/nitro-fs.nitro.ts b/src/specs/nitro-fs.nitro.ts index ebc2670..8083092 100755 --- a/src/specs/nitro-fs.nitro.ts +++ b/src/specs/nitro-fs.nitro.ts @@ -114,13 +114,12 @@ export interface NitroFS extends HybridObject<{ ios: 'swift', android: 'kotlin' * Download a file from the internet to the file system * ```typescript * const serverUrl = 'https://example.com/download' - * const fileName = 'file.txt' * const destinationPath = NitroFS.DOWNLOAD_DIR + '/file.txt' - * const file = await NitroFS.downloadFile(serverUrl, fileName, destinationPath, (downloadedBytes, totalBytes) => { + * const file = await NitroFS.downloadFile(serverUrl, destinationPath, (downloadedBytes, totalBytes) => { * console.log(`Downloading ${downloadedBytes / totalBytes * 100}%`) * }) * console.log(file) // { name: 'file.txt', mimeType: 'text/plain', path: 'file.txt' } * ``` */ - downloadFile(serverUrl: string, fileName: string, destinationPath: string, onProgress?: (downloadedBytes: number, totalBytes: number) => void): Promise + downloadFile(serverUrl: string, destinationPath: string, onProgress?: (downloadedBytes: number, totalBytes: number) => void): Promise }