0

I let people download files using HTTP-GET from Yaws. I have implemented as it is done in yaws_appmod_dav.erl, and it works fine.

            case file:read(Fd,PPS) of
            {ok,Data} when size(Data)<PPS ->
                ?DEBUG("only chunk~n"),
                status(200,H,{content,Mimetype,Data});
            {ok,Data} ->
                ?DEBUG("first chunk~n"),
                spawn(fun() -> deliver_rest(Pid,Fd) end),
                status(200,H,{streamcontent,Mimetype,Data});
            eof ->
                status(200,{content,"application/octet-stream",<<>>});
            {error,Reason} ->
                Response = [{'D:error',[{'xmlns:D',"DAV:"}],[Reason]}],
                status(500,{xml,Response})
            end;

I would like to mark a successful download on the server, i.e. when the client has accepted the last package.

How do I do that?


A minor questions: In webdav-app for Yaws, yaws_api:stream_chunk_deliver is used instead yaws_api:stream_chunk_deliver_blocking when getting a file. (See row 449 in https://github.com/klacke/yaws/blob/master/src/yaws_appmod_dav.erl)

Why isn't this a problem? According to http://yaws.hyber.org/stream.yaws "Whenever the producer of the stream is faster than the consumer, that is the WWW client, we must use a synchronous version of the code. " I notice that both versions works fine, is it just the amount of memory on the server that is affected?

mattias
  • 870
  • 5
  • 18

1 Answers1

0

The HTTP protocol doesn't specify a way for the client to notify the server that a download has been successful. The client either gets the requested data confirmed by the result code 200 (or 206) or it doesn't, and in that case it gets one of the error codes. Then the client is free to re-request that data. So, there isn't a reliable way of achieving what you want.

You could record the fact that the last chunk of data has been sent to the client and assume that it has been successful, unless the client re-requests that data, in which case you can invalidate the previous assumption.

Also, please note that HTTP specification allows to request from the server any part of the data when it sends the GET request with the Range header. See an example in this fusefs-httpfs implementation and some more info in this SO post. How can you determine if the download has been successful if you don't know which GET request that uses Range header is the last one (e.g. the client may download the whole file in chunks in backward order).


This may also answer you minor question. The client controls the flow by requesting a specified range of bytes from the given file. I don't know the implementation of WebDAV protocol, but it's possible that it doesn't request the whole file at once, and so the server can deliver data in chunks and never overflow the client.

HTTP Range header is something separate from the TCP window size, which is at the TCP protocol level (HTTP is an application level protocol implemented on top of TCP). Say the client requested the whole file and the server sends it like that. It's not that the whole file has been send through the network yet. The data to be send is buffered in the kernel and send in chunks according to the TCP window size. Had the client requested only part of the data with the Range header, only that part would be buffered in the kernel.

Community
  • 1
  • 1
Greg
  • 8,230
  • 5
  • 38
  • 53