/// <summary> /// Uploads a file to Dropbox /// </summary> /// <param name="dropboxFilePath">The path to save the upload as within Dropbox</param> /// <param name="localFilePath">The local file to upload</param> /// <param name="overwrite">True to overwrite and existing file with the same name</param> /// <param name="cancelToken">The async cancellation token</param> /// <returns>The result of the asynchronous operation</returns> public async Task UploadFile(string dropboxFilePath, string localFilePath, bool overwrite, CancellationToken cancelToken) { using (FileStream stream = new FileStream(localFilePath, System.IO.FileMode.Open)) { FileTransferProgressArgs args = new FileTransferProgressArgs(localFilePath, dropboxFilePath, (ulong)stream.Length); if (FileTransferProgress != null) { FileTransferProgress(this, args); } if (stream.Length <= ChunkSize) { await _Dropbox.Files.UploadAsync(dropboxFilePath, WriteMode.Add.Instance, !overwrite, body : stream); } else { await ChunkUpload(stream, dropboxFilePath, ChunkSize, overwrite, args, cancelToken); } args.BytesTransfered = args.FileSize; if (FileTransferProgress != null) { FileTransferProgress(this, args); } } }
private void UpdateProgress(FileTransferProgressArgs e) { if (this.InvokeRequired) { this.Invoke(new MethodInvoker(() => { UpdateProgress(e); })); } else { progress.Value = e.Percentage; lblRemaining.Text = e.Remaining; } }
/// <summary> /// Downloads a file from Dropbox in chunks /// </summary> private async Task DownloadFileChunks(string dropboxFilePath, string localFilePath, CancellationToken cancelToken) { if (File.Exists(localFilePath)) { File.Delete(localFilePath); } var download = await _Dropbox.Files.DownloadAsync(dropboxFilePath); ulong fileSize = download.Response.Size; FileTransferProgressArgs args = new FileTransferProgressArgs(dropboxFilePath, localFilePath, fileSize); var buffer = new byte[ChunkSize]; // Open the stream and download a small chunk at a time so we can report proress using (var stream = await download.GetContentAsStreamAsync()) { using (var file = new FileStream(localFilePath, FileMode.OpenOrCreate)) { var asyncDownload = Task.Factory.StartNew(() => { var length = stream.Read(buffer, 0, ChunkSize); while (length > 0) { file.Write(buffer, 0, length); // Calculate and report progress args.BytesTransfered = (ulong)file.Length; if (FileTransferProgress != null) { FileTransferProgress(this, args); } length = stream.Read(buffer, 0, ChunkSize); if (cancelToken.IsCancellationRequested) { return; } } }); await asyncDownload; } } }
/// <summary> /// Uploads a file as multiple chunks with progress events /// </summary> private async Task ChunkUpload(FileStream stream, string dropboxFilePath, int chunkSize, bool overwrite, FileTransferProgressArgs args, CancellationToken cancelToken) { int numChunks = (int)Math.Ceiling((double)stream.Length / chunkSize); byte[] buffer = new byte[chunkSize]; string sessionId = null; for (var idx = 0; idx < numChunks; idx++) { var byteRead = stream.Read(buffer, 0, chunkSize); using (MemoryStream memStream = new MemoryStream(buffer, 0, byteRead)) { if (idx == 0) { var result = await _Dropbox.Files.UploadSessionStartAsync(false, memStream); sessionId = result.SessionId; args.BytesTransfered += (ulong)chunkSize; if (FileTransferProgress != null) { FileTransferProgress(this, args); } } else { UploadSessionCursor cursor = new UploadSessionCursor(sessionId, (ulong)(chunkSize * idx)); if (idx == numChunks - 1) { CommitInfo commit = new CommitInfo(dropboxFilePath, WriteMode.Add.Instance, !overwrite); await _Dropbox.Files.UploadSessionFinishAsync(cursor, commit, memStream); } else { await _Dropbox.Files.UploadSessionAppendV2Async(cursor, false, memStream); args.BytesTransfered += (ulong)chunkSize; if (FileTransferProgress != null) { FileTransferProgress(this, args); } } } } if (cancelToken.IsCancellationRequested) { return; } } }
private void Dropbox_FileTransferProgress(object sender, FileTransferProgressArgs e) { UpdateProgress(e); }