You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by rn...@apache.org on 2010/08/24 11:43:59 UTC

svn commit: r988451 - /couchdb/trunk/src/couchdb/couch_httpd_db.erl

Author: rnewson
Date: Tue Aug 24 09:43:59 2010
New Revision: 988451

URL: http://svn.apache.org/viewvc?rev=988451&view=rev
Log:
support multiple byte ranges in Range header.

Modified:
    couchdb/trunk/src/couchdb/couch_httpd_db.erl

Modified: couchdb/trunk/src/couchdb/couch_httpd_db.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_httpd_db.erl?rev=988451&r1=988450&r2=988451&view=diff
==============================================================================
--- couchdb/trunk/src/couchdb/couch_httpd_db.erl (original)
+++ couchdb/trunk/src/couchdb/couch_httpd_db.erl Tue Aug 24 09:43:59 2010
@@ -775,9 +775,32 @@ send_docs_multipart(Req, Results, Option
     couch_httpd:send_chunk(Resp, <<"--">>),
     couch_httpd:last_chunk(Resp).
 
+send_ranges_multipart(Req, ContentType, Len, Att, Ranges) ->
+    Boundary = couch_uuids:random(),
+    CType = {"Content-Type",
+        "multipart/byteranges; boundary=\"" ++ ?b2l(Boundary) ++ "\""},
+    {ok, Resp} = start_chunked_response(Req, 206, [CType]),
+    couch_httpd:send_chunk(Resp, <<"--", Boundary/binary>>),
+    lists:foreach(fun({From, To}) ->
+        ContentRange = make_content_range(From, To, Len),
+        couch_httpd:send_chunk(Resp,
+            <<"\r\nContent-Type: ", ContentType/binary, "\r\n",
+            "Content-Range: ", ContentRange/binary, "\r\n",
+           "\r\n">>),
+        couch_doc:range_att_foldl(Att, From, To + 1,
+            fun(Seg, _) -> send_chunk(Resp, Seg) end, {ok, Resp}),
+        couch_httpd:send_chunk(Resp, <<"\r\n--", Boundary/binary>>)
+    end, Ranges),
+    couch_httpd:send_chunk(Resp, <<"--">>),
+    couch_httpd:last_chunk(Resp),
+    {ok, Resp}.
+
 receive_request_data(Req) ->
     {couch_httpd:recv(Req, 0), fun() -> receive_request_data(Req) end}.
     
+make_content_range(From, To, Len) ->
+    ?l2b(io_lib:format("bytes ~B-~B/~B", [From, To, Len])).
+
 update_doc_result_to_json({{Id, Rev}, Error}) ->
         {_Code, Err, Msg} = couch_httpd:error_info(Error),
         {[{id, Id}, {rev, couch_doc:rev_to_str(Rev)},
@@ -929,13 +952,13 @@ db_attachment_req(#httpd{method='GET',mo
                     Ranges = parse_ranges(MochiReq:get(range), Len),
                     case {Enc, Ranges} of
                         {identity, [{From, To}]} ->
-                            Headers1 = [{<<"Content-Range">>,
-                                ?l2b(io_lib:format("bytes ~B-~B/~B", [From, To, Len]))}]
+                            Headers1 = [{<<"Content-Range">>, make_content_range(From, To, Len)}]
                                 ++ Headers,
                             {ok, Resp} = start_response_length(Req, 206, Headers1, To - From + 1),
                             couch_doc:range_att_foldl(Att, From, To + 1,
                                 fun(Seg, _) -> send(Resp, Seg) end, {ok, Resp});
-                        %% {identity, Ranges} when is_list(Ranges) ->
+                        {identity, Ranges} when is_list(Ranges) ->
+                            send_ranges_multipart(Req, Type, Len, Att, Ranges);
                         _ ->
                             {ok, Resp} = start_response_length(Req, 200, Headers, Len),
                             AttFun(Att, fun(Seg, _) -> send(Resp, Seg) end, {ok, Resp})