From 06bea324270b0f66f7db0e9a005e198efe636dcc Mon Sep 17 00:00:00 2001 From: jld3103 Date: Sat, 5 Aug 2023 15:35:21 +0200 Subject: [PATCH] feat(nextcloud): Add get/put files operations to WebDAV --- packages/nextcloud/lib/src/webdav/client.dart | 54 +++++++++++++++++++ packages/nextcloud/test/files/test.txt | 1 - packages/nextcloud/test/webdav_test.dart | 24 +++++++++ 3 files changed, 78 insertions(+), 1 deletion(-) delete mode 100644 packages/nextcloud/test/files/test.txt diff --git a/packages/nextcloud/lib/src/webdav/client.dart b/packages/nextcloud/lib/src/webdav/client.dart index 108ec64f..3f67d7ca 100644 --- a/packages/nextcloud/lib/src/webdav/client.dart +++ b/packages/nextcloud/lib/src/webdav/client.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:convert'; import 'dart:typed_data'; @@ -169,6 +170,33 @@ class WebDavClient { ), ); + /// Puts a new file at [path] with [file] as content. + /// + /// [lastModified] sets the date when the file was last modified on the server. + /// [created] sets the date when the file was created on the server. + /// See http://www.webdav.org/specs/rfc2518.html#METHOD_PUT for more information. + Future putFile( + final File file, + final FileStat fileStat, + final String path, { + final DateTime? lastModified, + final DateTime? created, + final Function(double progres)? onProgress, + }) async { + var uploaded = 0; + return putStream( + file.openRead().map((final chunk) { + uploaded += chunk.length; + onProgress?.call(uploaded / fileStat.size * 100); + return Uint8List.fromList(chunk); + }), + path, + lastModified: lastModified, + created: created, + contentLength: fileStat.size, + ); + } + /// Gets the content of the file at [path]. Future get(final String path) async => (await getStream(path)).bodyBytes; @@ -178,6 +206,32 @@ class WebDavClient { _constructPath(path), ); + /// Gets the content of the file at [path]. + Future getFile( + final String path, + final File file, { + final Function(double progress)? onProgress, + }) async { + final sink = file.openWrite(); + final response = await getStream(path); + if (response.contentLength > 0) { + final completer = Completer(); + var downloaded = 0; + + response.listen((final chunk) async { + sink.add(chunk); + downloaded += chunk.length; + onProgress?.call(downloaded / response.contentLength * 100); + if (downloaded >= response.contentLength) { + completer.complete(); + } + }); + await completer.future; + } + + await sink.close(); + } + /// Retrieves the props for the resource at [path]. /// /// Optionally populates the given [prop]s on the returned files. diff --git a/packages/nextcloud/test/files/test.txt b/packages/nextcloud/test/files/test.txt deleted file mode 100644 index bbf5fc92..00000000 --- a/packages/nextcloud/test/files/test.txt +++ /dev/null @@ -1 +0,0 @@ -Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum diff --git a/packages/nextcloud/test/webdav_test.dart b/packages/nextcloud/test/webdav_test.dart index 13e466dc..94b39e5d 100644 --- a/packages/nextcloud/test/webdav_test.dart +++ b/packages/nextcloud/test/webdav_test.dart @@ -2,6 +2,7 @@ library webdav_test; import 'dart:convert'; +import 'dart:io'; import 'dart:math'; import 'dart:typed_data'; @@ -277,6 +278,29 @@ void main() { expect(props.ocfavorite, 0); }); + test('Upload and download file', () async { + final destinationDir = Directory.systemTemp.createTempSync(); + final destination = File('${destinationDir.path}/test.png'); + final source = File('test/files/test.png'); + final progressValues = []; + + await client.webdav.putFile( + source, + source.statSync(), + 'test.png', + onProgress: progressValues.add, + ); + await client.webdav.getFile( + 'test.png', + destination, + onProgress: progressValues.add, + ); + expect(progressValues, [100.0, 100.0]); + expect(destination.readAsBytesSync(), source.readAsBytesSync()); + + destinationDir.deleteSync(recursive: true); + }); + group('litmus', () { group('basic', () { test('options', () async {