-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: at_file_share demo #169
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
0426569
feat: at_file_share demo
murali-shris 0ab01d3
feat: working version 1
murali-shris eebecd0
feat: working version 2 - added env, bucket name as params
murali-shris 43177a8
fix: added iv string
murali-shris 0151f7f
fix: readme changes
murali-shris dd13748
fix: review comments
murali-shris File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# https://dart.dev/guides/libraries/private-files | ||
# Created by `dart pub` | ||
.dart_tool/ | ||
|
||
pubspec.lock | ||
|
||
at_file_share.iml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
## 1.0.0 | ||
|
||
- Initial version. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#TODO | ||
|
||
Prerequisite: | ||
1. Storj account and access grant | ||
1. Login/signup to https://www.storj.io/ | ||
2. Create new project e.g acme_demo | ||
3. Open the newly created project | ||
4. Go to buckets https://us1.storj.io/buckets/management and create new bucket e.g demo-bucket | ||
5. Go to access tab https://us1.storj.io/access-grants and click "create access grant" | ||
6. Type --> "Access Grant" and give a name to identify the access e.g acme-access. Click continue | ||
7. Under bucket select the bucket that you created i.e demo-bucket | ||
8. Create/enter a passphrase and click "create access".Click confirm | ||
9. Download the credentials file(acme-access.txt) by clicking "Download" | ||
2. Configure uplink | ||
1. Follow the instructions to install uplink tool - https://docs.storj.io/learn/tutorials/quickstart-uplink-cli | ||
2. Run the below command with the credentials file downloaded | ||
3. uplink access import main acme-access.txt | ||
3. Run file sender on sending machine and file receiver on receiving machine. File receiver will receive notification through | ||
atprotocol and download the storj file, decrypt using atClient SDK method. | ||
|
||
Usage: | ||
1. File sender | ||
1. dart bin/at_file_share.dart -m send -a <sender_atsign> -r <receiver_atsign> -k <path_to_sender_atKeys_file> -f <path_of_file_to_send> -b <storj_bucket_name> -n <namespace> | ||
2. e.g. dart bin/at_file_share.dart -m send -s @alice -r @bob -k /home/user/@alice.atKeys -f /home/user/test_file.txt -b demo-bucket -n acme | ||
2. File receiver | ||
1. dart bin/at_file_share.dart -m receive -k <path_to_receiver_atKeysFile> -a <current_atsign> -o <download_path> -n <namespace> | ||
2. e.g dart bin/at_file_share.dart -m receive -k /home/user/@bob.atKeys -a @bob -o /home/user/downloads -n acme |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# This file configures the static analysis results for your project (errors, | ||
# warnings, and lints). | ||
# | ||
# This enables the 'recommended' set of lints from `package:lints`. | ||
# This set helps identify many issues that may lead to problems when running | ||
# or consuming Dart code, and enforces writing Dart using a single, idiomatic | ||
# style and format. | ||
# | ||
# If you want a smaller set of lints you can change this to specify | ||
# 'package:lints/core.yaml'. These are just the most critical lints | ||
# (the recommended set includes the core lints). | ||
# The core lints are also what is used by pub.dev for scoring packages. | ||
|
||
include: package:lints/recommended.yaml | ||
|
||
# Uncomment the following section to specify additional rules. | ||
|
||
# linter: | ||
# rules: | ||
# - camel_case_types | ||
|
||
# analyzer: | ||
# exclude: | ||
# - path/to/excluded/files/** | ||
|
||
# For more information about the core and recommended set of lints, see | ||
# https://dart.dev/go/core-lints | ||
|
||
# For additional information about configuring this file, see | ||
# https://dart.dev/guides/language/analysis-options |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import 'package:args/args.dart'; | ||
import 'package:at_client/at_client.dart'; | ||
import 'package:at_file_share/src/file_send_params.dart'; | ||
import 'package:at_file_share/src/service/file_receiver.dart'; | ||
import 'package:at_file_share/src/service/file_sender.dart'; | ||
import 'package:at_onboarding_cli/at_onboarding_cli.dart'; | ||
import 'package:at_cli_commons/at_cli_commons.dart'; | ||
|
||
const String version = '0.0.1'; | ||
|
||
ArgParser buildParser() { | ||
return CLIBase.argsParser | ||
..addOption('mode', | ||
abbr: 'm', mandatory: true, help: 'File sharing mode - send or receive') | ||
..addOption('receiver', | ||
abbr: 'r', mandatory: true, help: 'atsign receiving the shared file') | ||
..addOption('filePath', | ||
abbr: 'f', mandatory: false, help: 'path of file in local to share') | ||
..addOption('downloadDir', | ||
abbr: 'o', mandatory: false, help: 'download dir when receiving files') | ||
..addOption('bucketName', | ||
abbr: 'b', | ||
mandatory: false, | ||
help: 'bucket name of storj to upload the file'); | ||
} | ||
|
||
void printUsage(ArgParser argParser) { | ||
print('Usage: dart at_file_share.dart <flags> [arguments]'); | ||
print(argParser.usage); | ||
} | ||
|
||
void main(List<String> arguments) async { | ||
final ArgParser argParser = buildParser(); | ||
try { | ||
final ArgResults results = argParser.parse(arguments); | ||
// Process the parsed arguments. | ||
if (results.wasParsed('help')) { | ||
printUsage(argParser); | ||
return; | ||
} | ||
String mode = results['mode']; | ||
var atClient = (await CLIBase.fromCommandLineArgs(arguments)).atClient; | ||
print('mode: $mode'); | ||
if (mode == 'send') { | ||
String receiver = results['receiver']; | ||
var params = FileSendParams() | ||
..receiverAtSign = receiver | ||
..filePath = results['filePath'] | ||
..bucketName = results['bucketName']; | ||
|
||
await FileSender(atClient).sendFile(params); | ||
} else if (mode == 'receive') { | ||
await FileReceiver(atClient).receiveFile(results['downloadDir']); | ||
} | ||
} on FormatException catch (e) { | ||
// Print usage information if an invalid argument was provided. | ||
print(e.message); | ||
print(''); | ||
printUsage(argParser); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
class FileSendParams { | ||
late String receiverAtSign; | ||
int chunkSize = 1024; | ||
late String filePath; | ||
late String bucketName; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
import 'dart:convert'; | ||
import 'dart:io'; | ||
import 'dart:typed_data'; | ||
import 'package:http/http.dart' as http; | ||
|
||
import 'package:at_client/at_client.dart'; | ||
|
||
class FileReceiver { | ||
final AtClient _atClient; | ||
|
||
FileReceiver(this._atClient); | ||
|
||
Future<void> receiveFile(String downloadPath) async { | ||
_atClient.notificationService | ||
.subscribe() | ||
.listen((AtNotification atNotification) async { | ||
if (atNotification.id != '-1') { | ||
var fileName; | ||
try { | ||
print('notification Received: ${atNotification.toString()}'); | ||
var key = atNotification.key; | ||
var atValue = await _atClient.get(AtKey.fromString(key)); | ||
print(atValue.toString()); | ||
var valueJson = jsonDecode(atValue.value); | ||
var storjUrl = valueJson['fileUrl']; | ||
fileName = valueJson['fileName']; | ||
await downloadFileWithProgress( | ||
storjUrl, downloadPath, fileName, valueJson); | ||
} on Exception catch (e, trace) { | ||
print(e); | ||
print(trace); | ||
} on Error catch (e, trace) { | ||
print(e); | ||
print(trace); | ||
} | ||
} | ||
}); | ||
} | ||
|
||
Future<void> _decryptFile( | ||
String downloadPath, String fileName, dynamic valueJson) async { | ||
try { | ||
var startTime = DateTime.now(); | ||
var encryptionService = _atClient.encryptionService!; | ||
var encryptedFile = | ||
File('$downloadPath${Platform.pathSeparator}encrypted_$fileName'); | ||
await encryptionService.decryptFileInChunks( | ||
encryptedFile, valueJson['fileEncryptionKey'], valueJson['chunkSize'], | ||
ivBase64: valueJson['iv']); | ||
var endTime = DateTime.now(); | ||
print( | ||
'Time taken to decrypt file: ${endTime.difference(startTime).inSeconds}'); | ||
var decryptedFile = File( | ||
"$downloadPath${Platform.pathSeparator}decrypted_encrypted_$fileName"); | ||
if (decryptedFile.existsSync()) { | ||
decryptedFile | ||
.renameSync(downloadPath + Platform.pathSeparator + fileName); | ||
} else { | ||
throw Exception('could not decrypt downloaded file'); | ||
} | ||
} on Exception catch (e, trace) { | ||
print(e); | ||
print(trace); | ||
} on Error catch (e, trace) { | ||
print(e); | ||
print(trace); | ||
} finally { | ||
var encryptedFile = | ||
File("$downloadPath${Platform.pathSeparator}encrypted_$fileName"); | ||
if (encryptedFile.existsSync()) { | ||
encryptedFile.deleteSync(); | ||
} | ||
} | ||
} | ||
|
||
Future<void> downloadFileWithProgress(String fileUrl, String downloadPath, | ||
String fileName, dynamic valueJson) async { | ||
var httpClient = http.Client(); | ||
var request = http.Request('GET', Uri.parse('$fileUrl?download=1')); | ||
var response = httpClient.send(request); | ||
|
||
List<List<int>> chunks = []; | ||
int downloaded = 0; | ||
|
||
response.asStream().listen((http.StreamedResponse r) { | ||
r.stream.listen((List<int> chunk) { | ||
if (r.contentLength == null) { | ||
print('content length is null.'); | ||
return; | ||
} | ||
// Display percentage of completion | ||
var percentage = downloaded / r.contentLength! * 100; | ||
int roundedPercent = percentage.round(); | ||
updateProgress(roundedPercent); | ||
|
||
chunks.add(chunk); | ||
downloaded += chunk.length; | ||
}, onDone: () async { | ||
// Display percentage of completion | ||
// print('downloadPercentage: ${downloaded / r.contentLength! * 100}'); | ||
|
||
// Save the file | ||
File file = | ||
File('$downloadPath${Platform.pathSeparator}encrypted_$fileName'); | ||
final Uint8List bytes = Uint8List(r.contentLength!); | ||
int offset = 0; | ||
for (List<int> chunk in chunks) { | ||
bytes.setRange(offset, offset + chunk.length, chunk); | ||
offset += chunk.length; | ||
} | ||
await file.writeAsBytes(bytes); | ||
await _decryptFile(downloadPath, fileName, valueJson); | ||
}); | ||
}); | ||
} | ||
|
||
void updateProgress(int progress) { | ||
// Move cursor to the beginning of the line | ||
stdout.write('\r'); | ||
|
||
// Print the progress in percentage | ||
stdout.write('Download progress: $progress%'); | ||
stdout.flush(); | ||
} | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you change the sender and receiver to use the CLIBase class instead, please? See https://github.com/atsign-foundation/at_demos/blob/trunk/at_rpc_demo/bin/arithmetic_client.dart for example
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks Gary. done