push method
Implementation
Future<OneDriveResponse> push(Uint8List bytes, String remotePath, {bool isAppFolder = false}) async {
final accessToken = await _tokenManager.getAccessToken();
if (accessToken == null) {
// No access token
return OneDriveResponse(message: "Null access token.");
}
try {
/// We need to call this method to create app folder and make sure it exists.
/// Otherwise, we will get "Access Denied - 403".
/// https://learn.microsoft.com/en-us/onedrive/developer/rest-api/concepts/special-folders-appfolder?view=odsp-graph-online
if (isAppFolder) {
await getMetadata(remotePath, isAppFolder: isAppFolder);
}
const int pageSize = 1024 * 1024; // page size
final int maxPage = (bytes.length / pageSize.toDouble()).ceil(); // total pages
// create upload session
// https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_createuploadsession?view=odsp-graph-online
var now = DateTime.now();
var url =
Uri.parse("$apiEndpoint/me/drive/${_getRootFolder(isAppFolder)}:$remotePath:/createUploadSession");
var resp = await http.post(
url,
headers: {"Authorization": "Bearer $accessToken"},
);
debugPrint("# Create Session: ${DateTime.now().difference(now).inMilliseconds} ms");
if (resp.statusCode == 200) {
// create session success
final Map<String, dynamic> respJson = jsonDecode(resp.body);
final String uploadUrl = respJson["uploadUrl"];
url = Uri.parse(uploadUrl);
// use upload url to upload
for (var pageIndex = 0; pageIndex < maxPage; pageIndex++) {
now = DateTime.now();
final int start = pageIndex * pageSize;
int end = start + pageSize;
if (end > bytes.length) {
end = bytes.length; // cannot exceed max length
}
final range = "bytes $start-${end - 1}/${bytes.length}";
final pageData = bytes.getRange(start, end).toList();
final contentLength = pageData.length.toString();
final headers = {
"Authorization": "Bearer $accessToken",
"Content-Length": contentLength,
"Content-Range": range,
};
resp = await http.put(
url,
headers: headers,
body: pageData,
);
debugPrint(
"# Upload [${pageIndex + 1}/$maxPage]: ${DateTime.now().difference(now).inMilliseconds} ms, start: $start, end: $end, contentLength: $contentLength, range: $range");
if (resp.statusCode == 202) {
// haven't finish, continue
continue;
} else if (resp.statusCode == 200 || resp.statusCode == 201) {
// upload finished
return OneDriveResponse(
statusCode: resp.statusCode, body: resp.body, message: "Upload finished.", isSuccess: true);
} else {
// has issue
return OneDriveResponse(statusCode: resp.statusCode, body: resp.body, message: "Upload failed.");
}
}
}
debugPrint("# Upload response: ${resp.statusCode}\n# Body: ${resp.body}");
} catch (err) {
debugPrint("# Upload error: $err");
return OneDriveResponse(message: "Unexpected exception: $err");
}
return OneDriveResponse(message: "Unexpected error.");
}