push method

Future<OneDriveResponse> push(
  1. Uint8List bytes,
  2. String remotePath, {
  3. bool isAppFolder = false,
})

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.");
}