@capacitor/filesystem 5.0.6-nightly-20230712T151609.0 → 5.1.1-nightly-20230713T150800.0

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.
@@ -1,4 +1,5 @@
1
1
  import Foundation
2
+ import Capacitor
2
3
 
3
4
  @objc public class Filesystem: NSObject {
4
5
 
@@ -21,6 +22,8 @@ import Foundation
21
22
  }
22
23
  }
23
24
 
25
+ public typealias ProgressEmitter = (_ bytes: Int64, _ contentLength: Int64) -> Void
26
+
24
27
  public func readFile(at fileUrl: URL, with encoding: String?) throws -> String {
25
28
  if encoding != nil {
26
29
  let data = try String(contentsOf: fileUrl, encoding: .utf8)
@@ -176,4 +179,158 @@ import Foundation
176
179
  return URL(string: path)
177
180
  }
178
181
  }
182
+
183
+ // swiftlint:disable function_body_length
184
+ @objc public func downloadFile(call: CAPPluginCall, emitter: @escaping ProgressEmitter, config: InstanceConfiguration?) throws {
185
+ let directory = call.getString("directory", "DOCUMENTS")
186
+ guard let path = call.getString("path") else {
187
+ call.reject("Invalid file path")
188
+ return
189
+ }
190
+
191
+ func handleDownload(downloadLocation: URL?, response: URLResponse?, error: Error?) {
192
+ if let error = error {
193
+ CAPLog.print("Error on download file", String(describing: downloadLocation), String(describing: response), String(describing: error))
194
+ call.reject(error.localizedDescription, "DOWNLOAD", error, nil)
195
+ return
196
+ }
197
+
198
+ if let httpResponse = response as? HTTPURLResponse {
199
+ HttpRequestHandler.setCookiesFromResponse(httpResponse, config)
200
+ }
201
+
202
+ guard let location = downloadLocation else {
203
+ call.reject("Unable to get file after downloading")
204
+ return
205
+ }
206
+
207
+ let fileManager = FileManager.default
208
+
209
+ if let foundDir = getDirectory(directory: directory) {
210
+ let dir = fileManager.urls(for: foundDir, in: .userDomainMask).first
211
+
212
+ do {
213
+ let dest = dir!.appendingPathComponent(path)
214
+ CAPLog.print("Attempting to write to file destination: \(dest.absoluteString)")
215
+
216
+ if !FileManager.default.fileExists(atPath: dest.deletingLastPathComponent().absoluteString) {
217
+ try FileManager.default.createDirectory(at: dest.deletingLastPathComponent(), withIntermediateDirectories: true, attributes: nil)
218
+ }
219
+
220
+ if FileManager.default.fileExists(atPath: dest.relativePath) {
221
+ do {
222
+ CAPLog.print("File already exists. Attempting to remove file before writing.")
223
+ try fileManager.removeItem(at: dest)
224
+ } catch let error {
225
+ call.reject("Unable to remove existing file: \(error.localizedDescription)")
226
+ return
227
+ }
228
+ }
229
+
230
+ try fileManager.moveItem(at: location, to: dest)
231
+ CAPLog.print("Downloaded file successfully! \(dest.absoluteString)")
232
+ call.resolve(["path": dest.absoluteString])
233
+ } catch let error {
234
+ call.reject("Unable to download file: \(error.localizedDescription)", "DOWNLOAD", error)
235
+ return
236
+ }
237
+ } else {
238
+ call.reject("Unable to download file. Couldn't find directory \(directory)")
239
+ }
240
+ }
241
+
242
+ guard var urlString = call.getString("url") else { throw URLError(.badURL) }
243
+ let method = call.getString("method", "GET")
244
+
245
+ let headers = (call.getObject("headers") ?? [:]) as [String: Any]
246
+ let params = (call.getObject("params") ?? [:]) as [String: Any]
247
+ let responseType = call.getString("responseType", "text")
248
+ let connectTimeout = call.getDouble("connectTimeout")
249
+ let readTimeout = call.getDouble("readTimeout")
250
+
251
+ if urlString == urlString.removingPercentEncoding {
252
+ guard let encodedUrlString = urlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else { throw URLError(.badURL) }
253
+ urlString = encodedUrlString
254
+ }
255
+
256
+ let progress = call.getBool("progress", false)
257
+
258
+ let request = try HttpRequestHandler.CapacitorHttpRequestBuilder()
259
+ .setUrl(urlString)
260
+ .setMethod(method)
261
+ .setUrlParams(params)
262
+ .openConnection()
263
+ .build()
264
+
265
+ request.setRequestHeaders(headers)
266
+
267
+ // Timeouts in iOS are in seconds. So read the value in millis and divide by 1000
268
+ let timeout = (connectTimeout ?? readTimeout ?? 600000.0) / 1000.0
269
+ request.setTimeout(timeout)
270
+
271
+ if let data = call.options["data"] as? JSValue {
272
+ do {
273
+ try request.setRequestBody(data)
274
+ } catch {
275
+ // Explicitly reject if the http request body was not set successfully,
276
+ // so as to not send a known malformed request, and to provide the developer with additional context.
277
+ call.reject(error.localizedDescription, (error as NSError).domain, error, nil)
278
+ return
279
+ }
280
+ }
281
+
282
+ var session: URLSession!
283
+ var task: URLSessionDownloadTask!
284
+ let urlRequest = request.getUrlRequest()
285
+
286
+ if progress {
287
+ class ProgressDelegate: NSObject, URLSessionDataDelegate, URLSessionDownloadDelegate {
288
+ private var handler: (URL?, URLResponse?, Error?) -> Void
289
+ private var downloadLocation: URL?
290
+ private var response: URLResponse?
291
+ private var emitter: (Int64, Int64) -> Void
292
+ private var lastEmitTimestamp: TimeInterval = 0.0
293
+
294
+ init(downloadHandler: @escaping (URL?, URLResponse?, Error?) -> Void, progressEmitter: @escaping (Int64, Int64) -> Void) {
295
+ handler = downloadHandler
296
+ emitter = progressEmitter
297
+ }
298
+
299
+ func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
300
+ let currentTimestamp = Date().timeIntervalSince1970
301
+ let timeElapsed = currentTimestamp - lastEmitTimestamp
302
+
303
+ if totalBytesExpectedToWrite > 0 {
304
+ if timeElapsed >= 0.1 {
305
+ emitter(totalBytesWritten, totalBytesExpectedToWrite)
306
+ lastEmitTimestamp = currentTimestamp
307
+ }
308
+ } else {
309
+ emitter(totalBytesWritten, 0)
310
+ lastEmitTimestamp = currentTimestamp
311
+ }
312
+ }
313
+
314
+ func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
315
+ downloadLocation = location
316
+ handler(downloadLocation, downloadTask.response, downloadTask.error)
317
+ }
318
+
319
+ func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
320
+ if error != nil {
321
+ handler(downloadLocation, task.response, error)
322
+ }
323
+ }
324
+ }
325
+
326
+ let progressDelegate = ProgressDelegate(downloadHandler: handleDownload, progressEmitter: emitter)
327
+ session = URLSession(configuration: .default, delegate: progressDelegate, delegateQueue: nil)
328
+ task = session.downloadTask(with: urlRequest)
329
+ } else {
330
+ task = URLSession.shared.downloadTask(with: urlRequest, completionHandler: handleDownload)
331
+ }
332
+
333
+ task.resume()
334
+ }
335
+ // swiftlint:enable function_body_length
179
336
  }
@@ -17,4 +17,5 @@ CAP_PLUGIN(FilesystemPlugin, "Filesystem",
17
17
  CAP_PLUGIN_METHOD(copy, CAPPluginReturnPromise);
18
18
  CAP_PLUGIN_METHOD(checkPermissions, CAPPluginReturnPromise);
19
19
  CAP_PLUGIN_METHOD(requestPermissions, CAPPluginReturnPromise);
20
+ CAP_PLUGIN_METHOD(downloadFile, CAPPluginReturnPromise);
20
21
  )
@@ -345,6 +345,23 @@ public class FilesystemPlugin: CAPPlugin {
345
345
  ])
346
346
  }
347
347
 
348
+ @objc func downloadFile(_ call: CAPPluginCall) {
349
+ guard let url = call.getString("url") else { return call.reject("Must provide a URL") }
350
+ let progressEmitter: Filesystem.ProgressEmitter = { bytes, contentLength in
351
+ self.notifyListeners("progress", data: [
352
+ "url": url,
353
+ "bytes": bytes,
354
+ "contentLength": contentLength
355
+ ])
356
+ }
357
+
358
+ do {
359
+ try implementation.downloadFile(call: call, emitter: progressEmitter, config: bridge?.config)
360
+ } catch let error {
361
+ call.reject(error.localizedDescription)
362
+ }
363
+ }
364
+
348
365
  /**
349
366
  * Helper for handling errors
350
367
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capacitor/filesystem",
3
- "version": "5.0.6-nightly-20230712T151609.0",
3
+ "version": "5.1.1-nightly-20230713T150800.0",
4
4
  "description": "The Filesystem API provides a NodeJS-like API for working with files on the device.",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",
@@ -45,10 +45,10 @@
45
45
  "publish:cocoapod": "pod trunk push ./CapacitorFilesystem.podspec --allow-warnings"
46
46
  },
47
47
  "devDependencies": {
48
- "@capacitor/android": "^5.0.0",
49
- "@capacitor/core": "^5.0.0",
48
+ "@capacitor/android": "^5.1.1",
49
+ "@capacitor/core": "^5.1.1",
50
50
  "@capacitor/docgen": "0.2.0",
51
- "@capacitor/ios": "^5.0.0",
51
+ "@capacitor/ios": "^5.1.1",
52
52
  "@ionic/eslint-config": "^0.3.0",
53
53
  "@ionic/prettier-config": "~1.0.1",
54
54
  "@ionic/swiftlint-config": "^1.1.2",
@@ -61,7 +61,7 @@
61
61
  "typescript": "~4.1.5"
62
62
  },
63
63
  "peerDependencies": {
64
- "@capacitor/core": "^5.0.0"
64
+ "@capacitor/core": "^5.1.1"
65
65
  },
66
66
  "prettier": "@ionic/prettier-config",
67
67
  "swiftlint": "@ionic/swiftlint-config",