Implement FR #3364: Add --download-file feature

* Add feature request --download-file to download a single file based on the online path
This commit is contained in:
abraunegg 2025-10-04 07:08:41 +10:00
commit fa35d64c41
3 changed files with 109 additions and 1 deletions

View file

@ -1132,6 +1132,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;
@ -1214,6 +1215,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"],
@ -2641,6 +2645,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
@ -2718,6 +2723,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;
}
@ -2801,6 +2812,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",
@ -2842,7 +2854,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

@ -745,6 +745,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

@ -14753,4 +14753,89 @@ class SyncEngine {
// Return sanitised JSON string for logging output
return sanitisedJSONString;
}
// 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);
}
}
}