Table of Contents

Uploading

TTMSFNCCloudDropBox uploads a local file into a Dropbox folder, reporting completion through an event. Dropbox accepts a file of up to 150 MB in a single request; anything larger has to be sent in chunks through a resumable upload session, which the component drives for you once you start it. This chapter covers a normal upload, the resumable session for large files, and how to choose between them.

Uploading a file

Upload sends a local file to a Dropbox folder. Use the folder-name overload for a path, or the folder-item overload when you already hold the target folder. OnUploadFile reports the created item. UploadMode controls the conflict behavior when an item with the same name already exists at the destination.

procedure TForm1.UploadReport;
begin
  TMSFNCCloudDropBox1.OnUploadFile := DropBoxUploaded;
  // Folder path; pass an empty string for the root.
  TMSFNCCloudDropBox1.Upload('/Reports', 'C:\local\Q4.pdf');
end;

procedure TForm1.DropBoxUploaded(Sender: TObject; const AUploadItem: TTMSFNCCloudItem;
  const ARequestResult: TTMSFNCCloudBaseRequestResult);
begin
  if ARequestResult.Success then
    ShowMessage('Uploaded as ' + AUploadItem.FileName)
  else
    ShowMessage('Upload failed: ' + ARequestResult.ResultString);
end;

Resumable uploads for large files

A file that will not fit in a single request goes through UploadResumableFile instead. This is a separate callUpload never switches to a resumable session on its own. Describe the transfer with a TTMSFNCCloudFile entry taken from the component's CloudFiles collection: FilePath is the local file and DestinationPath is the Dropbox folder it is written into (or pass the target folder item as the second argument to UploadResumableFile). The first call sends the first chunk; each following chunk is queued automatically from the previous one until the file is complete.

OnUploadResumableFile reports each chunk as it completes and is where you drive a progress bar — TTMSFNCCloudFile.Position holds the confirmed offset and GetFileSize the total. OnUploadResumableFileFinished fires once the last chunk lands, and OnUploadResumableFileFailed reports a failed chunk. Because Position and SessionID survive a failure, handing the same TTMSFNCCloudFile back to UploadResumableFile resumes the transfer where it stopped instead of restarting it.

procedure TForm1.UploadLargeFile;
var
  CloudFile: TTMSFNCCloudFile;
begin
  TMSFNCCloudDropBox1.OnUploadResumableFile := DropBoxChunkUploaded;
  TMSFNCCloudDropBox1.OnUploadResumableFileFinished := DropBoxUploadFinished;
  TMSFNCCloudDropBox1.OnUploadResumableFileFailed := DropBoxUploadFailed;

  // The resumable session is driven from a TTMSFNCCloudFile entry: FilePath is
  // the local file, DestinationPath the Dropbox folder it is written into.
  CloudFile := TMSFNCCloudDropBox1.CloudFiles.Add;
  CloudFile.FilePath := 'C:\local\database-backup.bak';
  CloudFile.DestinationPath := '/Backups';

  // Sends the first chunk; every following chunk is queued automatically from
  // the completion of the previous one until the file is fully uploaded.
  TMSFNCCloudDropBox1.UploadResumableFile(CloudFile);
end;

procedure TForm1.DropBoxChunkUploaded(Sender: TObject; const ACloudFile: TTMSFNCCloudFile;
  const ARequestResult: TTMSFNCCloudBaseRequestResult);
begin
  if ARequestResult.Success and (ACloudFile.GetFileSize > 0) then
    ProgressBar1.Value := ACloudFile.Position / ACloudFile.GetFileSize * 100;
end;

procedure TForm1.DropBoxUploadFinished(Sender: TObject; const ACloudFile: TTMSFNCCloudFile;
  const ARequestResult: TTMSFNCCloudBaseRequestResult);
begin
  if ARequestResult.Success then
    ShowMessage('Upload complete: ' + ACloudFile.FilePath);
end;

procedure TForm1.DropBoxUploadFailed(Sender: TObject; const ACloudFile: TTMSFNCCloudFile;
  const ARequestResult: TTMSFNCCloudBaseRequestResult);
begin
  // Position still holds the last confirmed offset, so the same CloudFile can
  // be handed to UploadResumableFile again to resume where it stopped.
  ShowMessage('Upload failed: ' + ARequestResult.ResultString);
end;

Choosing between a single and a resumable upload

Code that handles files of unpredictable size has to pick the path itself. Check the size first and route small files through Upload and large ones through UploadResumableFile, wiring both completion events so either outcome is reported:

procedure TForm1.UploadFileOfAnySize(const ALocalFile: string);
const
  ResumableThreshold = 100 * 1024 * 1024; // Dropbox caps a single upload at 150 MB.
var
  CloudFile: TTMSFNCCloudFile;
begin
  TMSFNCCloudDropBox1.OnUploadFile := DropBoxUploadFileDone;
  TMSFNCCloudDropBox1.OnUploadResumableFileFinished := DropBoxUploadResumableDone;
  TMSFNCCloudDropBox1.OnUploadResumableFileFailed := DropBoxUploadResumableFailed;

  CloudFile := TMSFNCCloudDropBox1.CloudFiles.Add;
  CloudFile.FilePath := ALocalFile;
  CloudFile.DestinationPath := '/Backups';

  if CloudFile.GetFileSize < ResumableThreshold then
    // Small enough for a single request; completes in OnUploadFile.
    TMSFNCCloudDropBox1.Upload(CloudFile.DestinationPath, CloudFile.FilePath)
  else
    // Too large for one request; completes in OnUploadResumableFileFinished.
    TMSFNCCloudDropBox1.UploadResumableFile(CloudFile);
end;

procedure TForm1.DropBoxUploadFileDone(Sender: TObject; const AUploadItem: TTMSFNCCloudItem;
  const ARequestResult: TTMSFNCCloudBaseRequestResult);
begin
  if ARequestResult.Success then
    ShowMessage('Uploaded as ' + AUploadItem.FileName);
end;

procedure TForm1.DropBoxUploadResumableDone(Sender: TObject; const ACloudFile: TTMSFNCCloudFile;
  const ARequestResult: TTMSFNCCloudBaseRequestResult);
begin
  if ARequestResult.Success then
    ShowMessage('Uploaded (resumable): ' + ACloudFile.FilePath);
end;

procedure TForm1.DropBoxUploadResumableFailed(Sender: TObject; const ACloudFile: TTMSFNCCloudFile;
  const ARequestResult: TTMSFNCCloudBaseRequestResult);
begin
  ShowMessage('Resumable upload failed: ' + ARequestResult.ResultString);
end;

Common mistakes

  • Assuming Upload is synchronous. Upload returns before the transfer finishes; act on the result in OnUploadFile (or, in synchronous mode, on the return value — see Folder and file operations).
  • Expecting Upload to chunk a large file. It does not. A file over the provider's single-request limit must go through UploadResumableFile, and it completes through OnUploadResumableFileFinished, never OnUploadFile.
  • Creating the TTMSFNCCloudFile yourself. Take it from CloudFiles.Add so the component owns it for the lifetime of the session; a resumable upload reads and updates Position, SessionID and Uploaded on that entry across several requests.
  • TTMSFNCCloudDropBoxUpload, UploadResumableFile, UploadMode, CloudFiles, OnUploadFile, OnUploadResumableFile, OnUploadResumableFileFinished, OnUploadResumableFileFailed

See also