From f3597fc4871cd5654a794144e1fef598078b3c5e Mon Sep 17 00:00:00 2001 From: Robert Newson Date: Tue, 24 Aug 2010 09:43:59 +0000 Subject: support multiple byte ranges in Range header. git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@988451 13f79535-47bb-0310-9956-ffa450edef68 --- src/couchdb/couch_httpd_db.erl | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/couchdb/couch_httpd_db.erl b/src/couchdb/couch_httpd_db.erl index 17b27b13..9181fcc5 100644 --- a/src/couchdb/couch_httpd_db.erl +++ b/src/couchdb/couch_httpd_db.erl @@ -775,9 +775,32 @@ send_docs_multipart(Req, Results, Options) -> 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',mochi_req=MochiReq}=Req, Db, DocId, FileNa 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}) -- cgit v1.2.3