Implementing Upload Progress in Java WebDAV Server

To support upload-progress report, you must implement ResumableUpload and UploadProgress interfaces on file items. Optionally you can implement UploadProgress on folder items.

Note that PUT with Content-Rage header is supported on any server based on Java WebDAV Server Library, there is no need to implement interfaces described here if you require only PUT with Content-Rage support.

To check if folder or file supports upload-progress report the client application will submit OPTIONS request to that item. If the item implements UploadProgress interface the Engine will add 'resumable-upload' token to DAV response header:

DAV: 1, 2, 3 resumable-upload

ResumableUpload Interface

The ResumableUpload interface provides methods for reporting total file size, amount of bytes being uploaded and time when the last chunk was saved. The total amount of bytes in file content is passed to your File.write method implementation. You must save it to your persistent storage and then return from your ResumableUpload.getTotalContentLength method implementation.

Often you will keep the old file content while uploading the new. In this case, you will return the old file content from your File.read() method and return the old file size from File.getContentLength(). The amount of bytes uploaded of new content must be returned from ResumableUpload.getBytesUploaded().

UploadProgress Interface

The implementation of this interface on file items is very simple - you must return List with a single item - this file item. Optionally you can implement this interface on folder items. In this case, you mast return all files that are being uploaded to the subtree.

When building output XML in response to upload-progress REPORT request the engine will call ResumableUpload.getTotalContentLength(), ResumableUpload.getBytesUploaded(), ResumableUpload.getLastChunkSaved() and HierarchyItem.getPath() for each item from the list and will return this information to client.

public class FileImpl implements File, ResumableUpload, UploadProgress {
    ...
    public void write(InputStream content, String contentType, long startIndex, long totalFileSize)
            throws LockedException, ServerException, IOException {
        ...
        // save totalFileSize in your persistent storage here
        ...
    }
    public long getTotalContentLength() {
        // return totalFileSize value saved in File.write method
    }
    public long getLastChunkSaved() throws ServerException {
        // return time of last File.write call;
    }
    public void cancelUpload() throws LockedException, ServerException {
        // client do not do not plan to restore the upload, 
        // delete any temporary files / cleanup resources here
    }   
    public long getBytesUploaded() throws ServerException{
        // return amount of bytes saved in your storage,
        // if you keep the old file content while uploading new, this value
        // will be different from the one retuned from File.getContentLength()
    }
    public boolean getCheckInOnFileComplete() throws ServerException {
        throw new ServerException("Not implemented");
    }
    public void setCheckInOnFileComplete(boolean value) throws ServerException {
        throw new ServerException("Not implemented");
    }
    public List<? extends ResumableUpload> getUploadProgress() throws ServerException {
        return Arrays.asList(this);
    }
}