abraunegg-onedrive/src/upload.d

98 lines
2.8 KiB
D

import std.algorithm;
import std.conv;
import std.datetime;
import std.file;
import std.json;
import std.stdio;
import onedrive;
private long fragmentSize = 10 * 2^^20; // 10 Mib
struct UploadSession
{
private OneDriveApi onedrive;
private bool verbose;
// https://dev.onedrive.com/resources/uploadSession.htm
private JSONValue session;
// path where to save the session
private string sessionFilePath;
this(OneDriveApi onedrive, string sessionFilePath, bool verbose)
{
assert(onedrive);
this.onedrive = onedrive;
this.sessionFilePath = sessionFilePath;
this.verbose = verbose;
}
JSONValue upload(string localPath, string remotePath, const(char)[] eTag = null)
{
session = onedrive.createUploadSession(remotePath, eTag);
session["localPath"] = localPath;
save();
return upload();
}
/* Restore the previous upload session.
* Returns true if the session is valid. Call upload() to resume it.
* Returns false if there is no session or the session is expired. */
bool restore()
{
if (exists(sessionFilePath)) {
if (verbose) writeln("Trying to restore the upload session ...");
session = readText(sessionFilePath).parseJSON();
auto expiration = SysTime.fromISOExtString(session["expirationDateTime"].str);
if (expiration < Clock.currTime()) {
if (verbose) writeln("The upload session is expired");
return false;
}
if (!exists(session["localPath"].str)) {
if (verbose) writeln("The file do not exist anymore");
return false;
}
// request the session status
auto response = onedrive.requestUploadStatus(session["uploadUrl"].str);
session["expirationDateTime"] = response["expirationDateTime"];
session["nextExpectedRanges"] = response["nextExpectedRanges"];
if (session["nextExpectedRanges"].array.length == 0) {
if (verbose) writeln("The upload session is completed");
return false;
}
return true;
}
return false;
}
JSONValue upload()
{
long offset = session["nextExpectedRanges"][0].str.splitter('-').front.to!long;
long fileSize = getSize(session["localPath"].str);
JSONValue response;
while (true) {
long fragSize = fragmentSize < fileSize - offset ? fragmentSize : fileSize - offset;
if (verbose) writeln("Uploading fragment: ", offset, "-", offset + fragSize, "/", fileSize);
response = onedrive.uploadFragment(
session["uploadUrl"].str,
session["localPath"].str,
offset,
fragSize,
fileSize
);
offset += fragmentSize;
if (offset >= fileSize) break;
// update the session
session["expirationDateTime"] = response["expirationDateTime"];
session["nextExpectedRanges"] = response["nextExpectedRanges"];
save();
}
// upload complete
remove(sessionFilePath);
return response;
}
private void save()
{
std.file.write(sessionFilePath, session.toString());
}
}