2.5.3 Resuming the Upload of a File

In this scenario, the client application will resume a previously interrupted file upload by detecting that the file to be uploaded to the server
already exists in the target folder, but in a “partially uploaded” state.

To support this kind of resume upload action, the Thru Server API has been extended to provide the client applications a method
to inquire whether there are any partially uploaded files in a given folder that match a provided file name list.

The method is not exposed as a traditional web service method, but, instead, is exposed as RESTful-type of endpoint, published in the following URL:

http(s)://<application-root>/WS4/FTHAppletService.ashx

The endpoint expects two parameters:

  • Operation:

GetInternalResumableUploadFiles (for internal uploads)

GetExternalResumableUploadFiles (for external uploads)

  • Message:

An FTHAppletUploadData structure, serialized as XML and URL-encoded (to support files with Unicode names).

As a result to this call, an FTHAppletUploadData structure, serialized as XML and URL-encoded, will be returned in the body of the response.

The FTHAppletUploadData structure is defined as:

<FTHAppletUploadData>
           <SessionID /> 
           <ParentFolderID />
           <UserID />
           <FileUploadData>
                      [<FTHFileUploadData>
                                  <FileID/>
                                  <Name/> 
                                  <ServerFilePath/>	
                                  <Size/>
                                  <PartialUpload/>
                      </FTHFileUploadData>]* (zero or more elements)
           </FileUploadData>
</FTHAppletUploadData>

In C# or Java, FTHAppletUploadData structure can be defined as:

FTHAppletUploadData
{
             String SessionID;
             int ParentFolderID;
             int UserID;
             FTHFileUploadData[] FileUploadData;
}
FTHFileUploadData
{
       int FileID;
       String Name;
       String ServerFilePath;
       long Size;
       bool PartialUpload;
}

The definition of each element of the FTHAppletUploadData structure is explained below.

FTHAppletUploadData

Element

Definition

SessionID

Contains the ID of the current session under which the upload operation is being performed. Required for the request message, with internal download operations.

ParentFolderID

The ID of the folder to which the files will be uploaded. Required for the request message, with internal download operations.

UserID

The ID of the user that owns the Dropbox folder to which the files will be uploaded. Required for the request message, with external download operations.

FileUploadData

An array with information for each file that will be uploaded to the server.

FileID

The ID of the corresponding partially uploaded file in the server. Returned by the response message.

Name

The name of the file being uploaded, with no directory information. Required for the request message. Uploaded files will be compared with existing files in the server based on their names. The server will also take in consideration versioned names. Files that were, upon upload, renamed to a different name with a sequential number (Uploaded “Image.jpg” => Saved Image1].jpg”)

ServerFilePath

The path in the server for the corresponding partially uploaded file. Returned by the response message.

Size

The size of the file being uploaded (request) or the current size of the corresponding partially uploaded file in the server (response). Required for the request message and returned by the response message.

PartialUpload

Indicates if the matching file in the server is partially uploaded. Returned by the response message. It will always have a value of “true” (see following explanation).

Note that the current protocol behavior is to re-add the uploaded file information to the FileUploadData array member in the response message,
if a matching file with partial content is found in the server.
As a result, the response message will probably contain fewer files than the request message submitted, since only the ones flagged with having a corresponding file with partial content (PartialUpload == true) will be returned.

Also, because of the way the protocol is designed, only allowing one parent folder ID (ParentFolderID) to be sent for each request, that implies that if user is uploading a multi-level set of files and folder, the client will have to send a separate message for each uploaded folder to inquire whether there are corresponding files with partial content in the folders.

So, we will walk through a real scenario, where 3 files will be uploaded through an internal upload operation:

One of them corresponding to a file whose upload has been previously interrupted.

Since it is an internal upload scenario, the app has connected to the server and been provided a Session ID (SessionID_NNN).

Also, the ID of target folder in the server is already known (RootFolderID_NNN).

As shown in the screenshot above, “Test.bmp,” “SP Connector.doc” and “7.5 Webinar.pptx” are being uploaded.

The first thing the client application needs to do is to send the “GetInternalResumableUploadFiles” message to the FTHAppletService endpoint in order to find out whether there are partially uploaded files in the server that correspond with the files to be uploaded.

GetInternalResumableUploadFiles Request

  • Operation: GetInternalResumableUploadFiles

  • Message:

<FTHAppletUploadData>
                    <SessionID>SessionID_NNN</SessionID>
                    <ParentFolderID>RootFolderID_NNN</ParentFolderID>
                    <UserID>0</UserID>
                    <FileUploadData>
                               <FTHFileUploadData>
                                           <FileID>0</FileID>
                                                    <Name>Test.bmp</Name> 
                                                    <ServerFilePath></ServerFilePath>
                                                    <Size>3072</Size>
                                                    <PartialUpload>false</PartialUpload>
                               </FTHFileUploadData>
                               <FTHFileUploadData>
                                           <FileID>0</FileID>
                                                    <Name>SP Connector.doc </Name> 
                                                    <ServerFilePath></ServerFilePath>
                                                    <Size>43008</Size>
                                                    <PartialUpload>false</PartialUpload>
                               </FTHFileUploadData>
                               <FTHFileUploadData>
                                           <FileID>0</FileID>
                                                    <Name>7.5 Webinar.pptx</Name> 
                                                    <ServerFilePath></ServerFilePath>
                                                    <Size>4508876</Size>
                                                    <PartialUpload>false</PartialUpload>
                               </FTHFileUploadData>
                               </FileUploadData>
</FTHAppletUploadData>

GetInternalResumableUploadFiles Response

Let’s assume that “7.5 Webinar.pptx” does exist in the target folder and is flagged as “Partial Upload”, while the other two files do not exist.

If the file in the server has a file ID of WebinarFileID_NNN, size of 2 MB and the target folder corresponds to the “/Presentations” server path, this would be the response returned to the client application.

<FTHAppletUploadData>
             <SessionID>SessionID_NNN</SessionID>
             <ParentFolderID>RootFolderID_NNN</ParentFolderID>
             <UserID>0</UserID>
             <FileUploadData>
                        <FTHFileUploadData>
                                    <FileID> WebinarFileID_NNN</FileID>
                                    <Name>7.5 Webinar.pptx</Name> 
                                    <ServerFilePath>/Presentations/7.5Webinar.pptx </ServerFilePath>
                                    <Size>2097152</Size>
                                    <PartialUpload>true</PartialUpload>
                        </FTHFileUploadData>
             </FileUploadData>
</FTHAppletUploadData>

With this information, the client application can start (either automatically or by requesting the user to confirm) an upload operation that will resume the previously interrupted upload operation.

Note that there is no explicit “Resume” action in the upload protocol. Instead, the client will use the chunked upload protocol to perform the upload with resume.

Here is the sequence of request to upload the three files.

The first request uploads two files (Test.bmp and “SP Connector.doc”)

Request 1

Form Fields

Example

Upload operation

Internal upload

Upload action

Upload file

InternalUpload_AppletUID
or
InternalUpload_SessionID

SessionID_NNN

ImmediateParentFolderID

RootFolderID_NNN

RootFolderID

RootFolderID_NNN

DeletePartiallyUploadedFile

0

File Fields

Example

name

File1

filename

Test.bmp

[content]

name

File2

filename

SP Connector.doc

[content]

As a result of a successful request, the server creates a new file system log operation entry (LogOpID_NNN) that will be associated with the upload operation and saves the uploaded files. The ID (FileID_NNN) of the last uploaded file of the set (“SP Connector.doc”) is returned in the headers.

Response 1

X-FileSystemLogOpID

LogOpID_NNN

X-FileID

FileID_NNN

X-FolderID

RootFolderID_NNN

The second request uploads the “7.5 Webinar.pptx” file. Instead of uploading the entire content of the file, the client application will use the information obtained through “GetInternalResumableUploadFiles” message to upload just the part of the file that is missing in the server.

For that, it will use the chunked upload protocol. Because the “first chunk” of the file is “already” in the server, the client app can start with a “upload file middle chunk” action (if more than one file chunk will be uploaded, due to the missing part of the file being very large) or go immediately to the “upload file last chunk” action (if the missing part fits in a single file chunk).

Because the missing part of “7.5 Webinar.pptx” has less than 3 MB, in this scenario the client app will only need one “upload file last chunk” request.

Request 2

Form Fields

Example

Upload operation

Internal upload

Upload action

Upload file last chunk

InternalUpload_AppletUID
or
InternalUpload_SessionID

SessionID_NNN

FileID

WebinarFileID_NNN

ImmediateParentFolderID

RootFolderID_NNN

RootFolderID

RootFolderID_NNN

FileSystemLogOpID

LogOpID_NNN

Overwrite

1

DeletePartiallyUploadedFile

0

ExpectedSizeBeforeAppendChunk

2,097,152 (2 MB)

File Fields

Example

name

File1

filename

7.5 Webinar.pptx

[final chunk – 2.3 MB]

Response 2

X-FileSystemLogOpID

LogOpID_NNN

X-FileID

WebinarFileID_NNN

X-FolderID

FolderID_NNN

Note that the “Overwrite” field in the request is set to “1.”

As defined by the protocol, in the case of a chunked upload that is being performed in order to resume the upload of a file, the “Overwrite” field should be set to true (“1”).