How Resumable Upload Works in Java WebDAV Server

Detecting resumable upload support

To detect if the server supports upload progress you must submit OPTIONS request:

OPTIONS /Folder/ HTTP/1.1
Content-Length: 0

If upload progress is supported the server will add 'resumable-upload' marker to its DAV header:

HTTP/1.1 200 OK
DAV: 1, 2, 3, resumable-upload
Content-Length: 0

Starting upload

Usually, you will start the upload submitting entire file content to server:

PUT /Folder/LargeFile.zip HTTP/1.1
Content-Length: 1923177918

Optionally you can attach the Content-Range header:

Content-Range: bytes 0-1944149437/1944149438

Pausing or breaking upload

To pause the upload, you simply break the connection. From the server point of view, there is no any difference if the connection was broken intentionally or if there were any network or client application failure. Note that this process is asynchronous and often server will still continue receiving bytes while client reports that the connection is broken/paused.

Requesting amount of bytes successfully saves on the server-side

To restore broken / paused upload you must first request how much of the file was successfully saved on the server side. As soon as there is no any standard way to request such information from the server, we provide proprietary upload-progress report for this purpose:

REPORT /Folder/LargeFile.zip HTTP/1.1
Content-Type: text/xml; charset="utf-8"
Content-Length: 75
<?xml version="1.0" encoding="utf-8"?>
<i:upload-progress xmlns:i="ithit" />

The server will respond with WebDAV Multi-Status response providing total file size, amount of bytes successfully uploaded and time when the last update happened:

207 Multi-Status
Content-Type: text/xml;charset=utf-8

<?xml version="1.0" ?>
<d:multistatus xmlns:d="DAV:">
   <d:response>
      <d:href>http://webdavserver.com/Folder/LargeFile.zip</d:href>
      <d:propstat>
         <d:status>HTTP/1.1 200 OK</d:status>
         <d:prop>
            <bytes-uploaded xmlns="ithit">20971520</bytes-uploaded>
            <last-chunk-saved xmlns="ithit">Thu, 26 Feb 2009 14:49:11 GMT</last-chunk-saved>
            <total-content-length xmlns="ithit">1944149438</total-content-length>
         </d:prop>
      </d:propstat>
   </d:response>
</d:multistatus>

Again, unlike most of other functionality provided by WebDAV server, this report in not part of WebDAV standard, and supported only by servers built on top of IT Hit WebDAV server libraries.

Here the description of each property in this report:

  • ithit:bytes-uploaded - integer value. Number of bytes uploaded and saved in persistent storage. If the upload was broken or paused the client application will usually start upload from the next byte returned in this property.
  • ithit:last-chunk-saved - date\time in RFC 1123 format. Indicates when last chunk was saved. May be used in admin applications and automatic maintenance tools to remove files that failed to upload.
  • ithit:total-content-length - integer value. Total file size that is being uploaded to the server. Thin client applications may use this value for displaying upload progress.

In case the REPORT is submitted over folder, the response will contain information about all files that are being uploaded to the subtree:

HTTP/1.1 207 Multi-Status
Content-Type: text/xml;charset=UTF-8
 <?xml version="1.0" ?>
 <D:multistatus xmlns:D="DAV:" xmlns:ithit="ithit">
 <D:response>
    <D:href>http://webdavserver.com/folder/LargeFile.zip</D:href>
    <D:propstat>
        <D:prop>
             <ithit:bytes-uploaded>20</ithit:bytes-uploaded>
             <ithit:last-chunk-saved>Wed, 23 May 2007 13:29:43 GMT</ithit:last-chunk-saved>
             <ithit:total-content-length>150742</ithit:total-content-length>    
       </D:prop>
       <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>        
 </D:response>        
 <D:response>
    <D:href>http://webdavserver.com/folder/nestedfolder/AnotherLargeFile.zip</D:href>
    <D:propstat>
        <D:prop>
             <ithit:bytes-uploaded>47</ithit:bytes-uploaded>
             <ithit:last-chunk-saved>Wed, 23 May 2007 13:16:12 GMT</ithit:last-chunk-saved>
             <ithit:total-content-length>6398</ithit:total-content-length>
       </D:prop>
       <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>        
 </D:response>        
</D:multistatus>

Resuming upload

Now when you know how much bytes were successfully uploaded you can restore the upload submitting PUT request with Content-Range header:

Content-Range: bytes 20971520-1944149437/1944149438
Content-Length: 1923177918

Cancelling upload

As soon as upload may take a long time, often you will keep the old file while uploading the new. You will serve the old file content in response to GET requests while the new content will be saved in temporary storage on the server until upload finishes. If the upload failed and you do not plan to restore upload you can submit the CANCELUPLOAD request:

CANCELUPLOAD /folder/LargeFile.zip

The server will be notified that it can remove any temporary files and clean up resources that were provided for this file upload. CANCELUPLOAD is proprietary IT Hit extension and is not part of WebDAV standard.

Next Article:

Implementing Upload Progress in Java WebDAV Server