locked
Downloading files RRS feed

  • Question

  • I need to download a file from an HTTP server, i would like to save the file locally with the file name being as specified by the server at the Content -Disposition, filename header. I don't want to specifiy the name myself (as i do not know it), like most of the functions i found require.
    Is there some class the supports that? or should i create the HTTP request myself, parse the header myself and save the file myself? if i must, what would be the best way to do that asynchronously?
    Tuesday, October 6, 2009 10:52 AM

Answers

  • This might get you started.  You will need to parse the Content-Disposition, sanitize it for security purposes, and then make a path on disk out of it.  Unfortunately doing this parsing 100% correctly is more difficult than I have time right now :(, so I must leave this as an exercise for you.  I think the relevant document is: http://www.ietf.org/rfc/rfc2183.txt

            private void button1_Click(object sender, EventArgs e)
            {
                WebClient wc = new WebClient();
                object tok = new object();
                wc.DownloadDataAsync(new Uri("http://put your URI here"), tok);
                wc.DownloadDataCompleted += DownloadDataCompletedProc;
            }
    
            private void DownloadDataCompletedProc(object sender, DownloadDataCompletedEventArgs e)
            {
                if (e.Cancelled)
                {
                    // Handle cancellation.
                }
                if (e.Error != null)
                {
                    // Handle error.
                }
                else
                {
                    WebClient wc = (WebClient) sender;
                    string disp = wc.ResponseHeaders["Content-Disposition"];
                    if (disp != null)
                    {
                        // Be on the lookout for security issues when you formulate the path.
                        System.IO.File.WriteAllBytes("put parsed path here", e.Result);
                    }
                    else
                    {
                        // Handle case where Content-Disposition header not returned.
                    }
                }
            }
    • Marked as answer by Magaf Thursday, October 8, 2009 10:23 AM
    Wednesday, October 7, 2009 11:30 PM

All replies

  • Are you taking about Content-Disposition: attachment?  This is frequently used on uploads but I've never seen it come back with a download.  Usually the filename is part of the download URL and you can parse it off easily (for example, by using System.Net.Uri and taking the last segment from its Segments property).  After you get the filename, use System.Net.WebClient.DownloadFileAsync to easily download the file asynchronously.
    Tuesday, October 6, 2009 11:00 PM
  • Are you taking about Content-Disposition: attachment?  This is frequently used on uploads but I've never seen it come back with a download.  Usually the filename is part of the download URL and you can parse it off easily (for example, by using System.Net.Uri and taking the last segment from its Segments property).  After you get the filename, use System.Net.WebClient.DownloadFileAsync to easily download the file asynchronously.
    Yes im talking about the Header:
    Content-Disposition: attachment; filename=bla.txt

    Its seems to be pretty commonly used, because most sites give you some kind of dynamic link instead of a the real file's path. I think browsers use this header when offering to save a file, so i thought a function called WebClient.DownloadFile would know how to use that.. but i found i need to give the file's name in advance.
    Which approach would you recommend for doing that?
    Wednesday, October 7, 2009 9:01 AM
  • This might get you started.  You will need to parse the Content-Disposition, sanitize it for security purposes, and then make a path on disk out of it.  Unfortunately doing this parsing 100% correctly is more difficult than I have time right now :(, so I must leave this as an exercise for you.  I think the relevant document is: http://www.ietf.org/rfc/rfc2183.txt

            private void button1_Click(object sender, EventArgs e)
            {
                WebClient wc = new WebClient();
                object tok = new object();
                wc.DownloadDataAsync(new Uri("http://put your URI here"), tok);
                wc.DownloadDataCompleted += DownloadDataCompletedProc;
            }
    
            private void DownloadDataCompletedProc(object sender, DownloadDataCompletedEventArgs e)
            {
                if (e.Cancelled)
                {
                    // Handle cancellation.
                }
                if (e.Error != null)
                {
                    // Handle error.
                }
                else
                {
                    WebClient wc = (WebClient) sender;
                    string disp = wc.ResponseHeaders["Content-Disposition"];
                    if (disp != null)
                    {
                        // Be on the lookout for security issues when you formulate the path.
                        System.IO.File.WriteAllBytes("put parsed path here", e.Result);
                    }
                    else
                    {
                        // Handle case where Content-Disposition header not returned.
                    }
                }
            }
    • Marked as answer by Magaf Thursday, October 8, 2009 10:23 AM
    Wednesday, October 7, 2009 11:30 PM
  • Thanks BinaryCoder, You pointed me exactly at the right direction.
    I used the System.Net.Mime.ContentDisposition class to parse the header.
    btw you called DownloadDataAsync before you set the DownloadDataCompleted handler, i just changed the order to make more sense.
    Thursday, October 8, 2009 10:23 AM
  • > I used the System.Net.Mime.ContentDisposition class to parse the header.

    I didn't know about that class.  Thanks :)

    > btw you called DownloadDataAsync before you set the DownloadDataCompleted handler, i just changed the order to make more sense.

    You are correct.  Thanks :)

    Thursday, October 8, 2009 10:35 PM