Re: Resumable Uploads

Mark Nottingham <> Sun, 21 April 2013 02:09 UTC

Return-Path: <>
Received: from localhost (localhost []) by (Postfix) with ESMTP id 0DE0B21F86FA for <>; Sat, 20 Apr 2013 19:09:40 -0700 (PDT)
X-Virus-Scanned: amavisd-new at
X-Spam-Flag: NO
X-Spam-Score: -10.443
X-Spam-Status: No, score=-10.443 tagged_above=-999 required=5 tests=[AWL=0.156, BAYES_00=-2.599, RCVD_IN_DNSWL_HI=-8]
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id p1EirEpfpd6K for <>; Sat, 20 Apr 2013 19:09:39 -0700 (PDT)
Received: from ( []) by (Postfix) with ESMTP id 3EB3421F86C3 for <>; Sat, 20 Apr 2013 19:09:39 -0700 (PDT)
Received: from lists by with local (Exim 4.72) (envelope-from <>) id 1UTjiH-0004qq-N1 for; Sun, 21 Apr 2013 02:09:09 +0000
Resent-Date: Sun, 21 Apr 2013 02:09:09 +0000
Resent-Message-Id: <>
Received: from ([]) by with esmtp (Exim 4.72) (envelope-from <>) id 1UTjiE-0004pv-65 for; Sun, 21 Apr 2013 02:09:06 +0000
Received: from ([]) by with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.72) (envelope-from <>) id 1UTjiD-0005m7-BE for; Sun, 21 Apr 2013 02:09:06 +0000
Received: from (unknown []) (using TLSv1 with cipher AES128-SHA (128/128 bits)) (No client certificate requested) by (Postfix) with ESMTPSA id DD994509B5; Sat, 20 Apr 2013 22:08:42 -0400 (EDT)
Content-Type: text/plain; charset="iso-8859-1"
Mime-Version: 1.0 (Mac OS X Mail 6.3 \(1503\))
From: Mark Nottingham <>
In-Reply-To: <>
Date: Sun, 21 Apr 2013 12:08:39 +1000
Cc: Felix Geisendörfer <>, HTTP Working Group <>
Content-Transfer-Encoding: quoted-printable
Message-Id: <>
References: <> <> <> <>
To: Yoav Nir <>
X-Mailer: Apple Mail (2.1503)
Received-SPF: pass client-ip=;;
X-W3C-Hub-Spam-Status: No, score=-3.3
X-W3C-Hub-Spam-Report: AWL=-3.282, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001
X-W3C-Scan-Sig: 1UTjiD-0005m7-BE 21c1e43b95fa1f4a528b7eaf0024d21e
Subject: Re: Resumable Uploads
Archived-At: <>
X-Mailing-List: <> archive/latest/17442
Precedence: list
List-Id: <>
List-Help: <>
List-Post: <>
List-Unsubscribe: <>

On 21/04/2013, at 5:43 AM, Yoav Nir <> wrote:

> On Apr 20, 2013, at 11:30 AM, Felix Geisendörfer <> wrote:
>> On Sat, Apr 20, 2013 at 7:59 AM, Mark Nottingham <> wrote:
>> Agreed, except a new PATCH format that's range-friendly would be necessary. That's not a huge undertaking, because it could reuse at least some of the existing syntax.
>> IMO the simplest solution would be an "Offset" header that simply gives the start offset where the data should be applied. The end offset is implicit through the message length.
> How does the server know when the whole thing has been uploaded?  Wouldn't we need some kind of "total-length" header, perhaps in the initial PUT?
> Or are we assuming that the initial PUT is trying to upload everything, and only failure leads to sending the PATCH?

One possibility would be to have a flag in the request (header or body) that indicates that after this PATCH, it's complete. E.g.,

PUT /foo HTTP/1.1  # create the new resource

PATCH /foo HTTP/1.1  # start uploading it...
PATCH /foo HTTP/1.1  # continue...

PATCH /foo HTTP/1.1
Upload-Complete: 1  # we're done!

You'd need conditionals (probably, if-match) on each PATCH to make sure it hasn't changed since the last PATCH (or PUT).

The PUT give the server an opportunity to refuse the request, and its response can advertise the details of how to PATCH it.

The only difficult part I can see is figuring out what to return to a GET that occurs before the upload is complete. And maybe how long to keep these partially-uploaded resources around (although that's really a server implementation detail).

It'd be nice if the PATCH format could modify headers cleanly too.


Mark Nottingham