Implement FR #3364: Add --download-file feature (#3459)

* Add feature request --download-file to download a single file based on the online path
This commit is contained in:
abraunegg 2025-10-07 18:07:05 +11:00 committed by GitHub
commit 18d267912e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 119 additions and 1 deletions

View file

@ -86,6 +86,7 @@ Before reading this document, please ensure you are running application version
- [CLI Option: --display-config](#cli-option---display-config)
- [CLI Option: --display-sync-status](#cli-option---display-sync-status)
- [CLI Option: --display-quota](#cli-option---display-quota)
- [CLI Option: --download-file](#cli-option---download-file)
- [CLI Option: --force](#cli-option---force)
- [CLI Option: --force-sync](#cli-option---force-sync)
- [CLI Option: --get-file-link](#cli-option---get-file-link)
@ -1358,6 +1359,11 @@ _**Description:**_ This CLI option will display the quota status of the account
_**Usage Example:**_ `onedrive --display-quota`
### CLI Option: --download-file
_**Description:**_ This CLI option will download a single file based on the online path. No sync will be performed.
_**Usage Example:**_ `onedrive --download-file 'path/to/your/file/online'`
### CLI Option: --force
_**Description:**_ This CLI option enables the force the deletion of data when a 'big delete' is detected.

View file

@ -188,6 +188,10 @@ Disable upload validation when uploading to OneDrive.
\fB\-\-display-quota\fR
Display the quota status of the client - no sync will be performed.
.TP
\fB\-\-download-file\fR
This CLI option will download a single file based on the online path. No sync will be performed.
.TP
\fB\-\-display-running-config\fR
Display what options the client has been configured to use on application startup.

View file

@ -1144,6 +1144,7 @@ class ApplicationConfig {
stringValues["auth_files"] = "";
stringValues["auth_response"] = "";
stringValues["share_password"] = "";
stringValues["download_single_file"] = "";
boolValues["display_config"] = false;
boolValues["display_sync_status"] = false;
boolValues["display_quota"] = false;
@ -1226,6 +1227,9 @@ class ApplicationConfig {
"download-only",
"Replicate the OneDrive online state locally, by only downloading changes from OneDrive. Do not upload local changes to OneDrive",
&boolValues["download_only"],
"download-file",
"Download a single file from Microsoft OneDrive",
&stringValues["download_single_file"],
"dry-run",
"Perform a trial sync with no changes made",
&boolValues["dry_run"],
@ -2654,6 +2658,7 @@ class ApplicationConfig {
// - Are we just deleting a directory online, without any sync being performed?
// - Are we renaming or moving a directory?
// - Are we displaying the quota information?
// - Are we downloading a single file?
bool noSyncOperation = false;
// Return a true|false if any of these have been set, so that we use the 'dry-run' DB copy, to execute these tasks, in case the client is currently operational
@ -2731,6 +2736,12 @@ class ApplicationConfig {
noSyncOperation = true;
}
// Are we downloading a single file?
if ((getValueString("download_single_file") != "")) {
// flag that a no sync operation has been requested
noSyncOperation = true;
}
// Return result
return noSyncOperation;
}
@ -2814,6 +2825,7 @@ void outputLongHelp(Option[] opt) {
"--classify-as-big-delete",
"--create-share-link",
"--destination-directory",
"--download-file",
"--get-file-link",
"--get-O365-drive-id",
"--get-sharepoint-drive-id",
@ -2855,7 +2867,9 @@ void outputLongHelp(Option[] opt) {
writefln(" %s%s%s%s\n %s",
it.optLong,
it.optShort == "" ? "" : " " ~ it.optShort,
argsNeedingOptions.canFind(it.optLong) ? " ARG" : "",
argsNeedingOptions.canFind(it.optLong) ? " '<path or required value>'" : "",
it.required ? " (required)" : "", it.help);
}
// end with a blank line
writeln();
}

View file

@ -747,6 +747,15 @@ int main(string[] cliArgs) {
return EXIT_SUCCESS;
}
// --download-file - Are we downloading a single file from Microsoft OneDrive
if ((appConfig.getValueString("download_single_file") != "")) {
// Handle downloading the single file
syncEngineInstance.downloadSingleFile(appConfig.getValueString("download_single_file"));
// Exit application
// Use exit scopes to shutdown API
return EXIT_SUCCESS;
}
// If we get to this point, we have not performed a 'no-sync' task ..
// Did we just authorise the client?

View file

@ -14836,4 +14836,89 @@ class SyncEngine {
displayFunctionProcessingTime(thisFunctionName, functionStartTime, Clock.currTime(), logKey);
}
}
// Download a single file via --download-file <path/to/file>
void downloadSingleFile(string pathToQuery) {
// Function Start Time
SysTime functionStartTime;
string logKey;
string thisFunctionName = format("%s.%s", strip(__MODULE__) , strip(getFunctionName!({})));
// Only set this if we are generating performance processing times
if (appConfig.getValueBool("display_processing_time") && debugLogging) {
functionStartTime = Clock.currTime();
logKey = generateAlphanumericString();
displayFunctionProcessingStart(thisFunctionName, logKey);
}
OneDriveApi queryPathDetailsOnline;
JSONValue onlinePathData;
// Was a path to query passed in?
if (pathToQuery.empty) {
// Nothing to query
addLogEntry("No path to query");
return;
}
// Create new OneDrive API Instance
queryPathDetailsOnline = new OneDriveApi(appConfig);
queryPathDetailsOnline.initialise();
try {
// Query the OneDrive API, using the path, which will query 'our' OneDrive Account
onlinePathData = queryPathDetailsOnline.getPathDetails(pathToQuery);
} catch (OneDriveException exception) {
if (exception.httpStatusCode == 404) {
// Path does not exist online ...
addLogEntry("ERROR: The requested path does not exist online. Please check for your file online.");
} else {
// Display error message
displayOneDriveErrorMessage(exception.msg, thisFunctionName);
}
// OneDrive API Instance Cleanup - Shutdown API, free curl object and memory
queryPathDetailsOnline.releaseCurlEngine();
queryPathDetailsOnline = null;
// Perform Garbage Collection
GC.collect();
// Return .. nothing to do
return;
}
// Was a valid JSON response provided?
if (onlinePathData.type() == JSONType.object) {
// Valid JSON item was returned
// Is the item a file ?
if (isFileItem(onlinePathData)) {
// JSON item is a file
// Download the file based on the data returned
downloadFileItem(onlinePathData);
} else {
// The provided path is not a file
addLogEntry();
addLogEntry("ERROR: The requested path to download is not a file. Please correct this error and try again.");
addLogEntry();
}
} else {
addLogEntry();
addLogEntry("ERROR: The requested file to download has generated an error. Please correct this error and try again.");
addLogEntry();
}
// OneDrive API Instance Cleanup - Shutdown API, free curl object and memory
queryPathDetailsOnline.releaseCurlEngine();
queryPathDetailsOnline = null;
// Perform Garbage Collection
GC.collect();
// Display function processing time if configured to do so
if (appConfig.getValueBool("display_processing_time") && debugLogging) {
// Combine module name & running Function
displayFunctionProcessingTime(thisFunctionName, functionStartTime, Clock.currTime(), logKey);
}
}
}