Получить имя файла при загрузке - PullRequest
24 голосов
/ 04 ноября 2010

Мы предоставляем файлы, которые сохранены в нашей базе данных, и единственный способ получить их - перейти по их id как в:

www.AwesomeURL.com/AwesomeSite.aspx?requestedFileId=23

Все работает файлпоскольку я использую класс WebClient .

Есть только одна проблема, с которой я сталкиваюсь:

Как я могу получить настоящее имя файла?

Мой код выглядит следующим образом:

WebClient client = new WebClient ();

string url = "www.AwesomeURL.com/AwesomeSite.aspx?requestedFileId=23";

client.DownloadFile(url, "IDontKnowHowToGetTheRealFileNameHere.txt");

Все, что я знаю, это id .

Этого не происходит, когда я пытаюсь получить доступ к url из браузера, где он получает правильное имя => DownloadedFile.xls .

Как правильно получить правильный ответ?

Ответы [ 6 ]

25 голосов
/ 21 марта 2012

У меня была такая же проблема, и я нашел этот класс: System.Net.Mime.ContentDisposition .

using (WebClient client = new WebClient()){
    client.OpenRead(url);

    string header_contentDisposition = client.ResponseHeaders["content-disposition"];
    string filename = new ContentDisposition(header_contentDisposition).FileName;

    ...do stuff...
}

Документация класса предполагает, что она предназначена для вложений электронной почты, но онаотлично работает на сервере, который я использовал для тестирования, и очень приятно избегать анализа.

23 голосов
/ 04 ноября 2010

Вот полный требуемый код, при условии, что сервер применил заголовок размещения контента:

using (WebClient client = new WebClient())
{
    using (Stream rawStream = client.OpenRead(url))
    {
        string fileName = string.Empty;
        string contentDisposition = client.ResponseHeaders["content-disposition"];
        if (!string.IsNullOrEmpty(contentDisposition))
        {
            string lookFor = "filename=";
            int index = contentDisposition.IndexOf(lookFor, StringComparison.CurrentCultureIgnoreCase);
            if (index >= 0)
                fileName = contentDisposition.Substring(index + lookFor.Length);
        }
        if (fileName.Length > 0)
        {
            using (StreamReader reader = new StreamReader(rawStream))
            {
                File.WriteAllText(Server.MapPath(fileName), reader.ReadToEnd());
                reader.Close();
            }
        }
        rawStream.Close();
    }
}

Если сервер не настроил этот заголовок, попробуйте отладку и посмотрите, какие у вас есть ResponseHeaders, один из них, вероятно, будет содержать желаемое имя. Если в браузере отображается имя, оно должно быть из где-то ..:)

9 голосов
/ 04 ноября 2010

Вам нужно взглянуть на заголовок content-disposition через:

string disposition = client.ResponseHeaders["content-disposition"];

типичным примером будет:

"attachment; filename=IDontKnowHowToGetTheRealFileNameHere.txt"
3 голосов
/ 04 ноября 2010

Вы можете использовать заголовок HTTP content-disposition, чтобы предложить имена файлов для предоставляемого вами контента:

Content-Disposition: attachment; filename=downloadedfile.xls;

Итак, в вашем скрипте AwesomeSite.aspx вы должны установить заголовок content-disposition. В вашем классе WebClient вы получите этот заголовок, чтобы сохранить файл, как предложено вашим сайтом AwesomeSite.

2 голосов
/ 26 апреля 2016

Я достигаю этого с помощью кода wst.

Вот полный код для загрузки файла URL в папку c: \ temp

public static void DownloadFile(string url)
    {
        using (WebClient client = new WebClient())
        {
            client.OpenRead(url);

            string header_contentDisposition = client.ResponseHeaders["content-disposition"];
            string filename = new ContentDisposition(header_contentDisposition).FileName;


            //Start the download and copy the file to the destinationFolder
            client.DownloadFile(new Uri(url), @"c:\temp\" + filename);
        }

    }
0 голосов
/ 14 января 2019

Хотя решение, предложенное Shadow Wizard, хорошо работает для текстовых файлов, мне нужно было поддерживать загрузку двоичных файлов, таких как изображения и исполняемые файлы, в моем приложении.

Вот небольшое расширение WebClient, котороеделает трюк.Загрузка асинхронная.Также требуется значение по умолчанию для имени файла, потому что мы не знаем, отправит ли сервер все нужные заголовки.

static class WebClientExtensions
{
    public static async Task<string> DownloadFileToDirectory(this WebClient client, string address, string directory, string defaultFileName)
    {
        if (!Directory.Exists(directory))
            throw new DirectoryNotFoundException("Downloads directory must exist");

        string filePath = null;

        using (var stream = await client.OpenReadTaskAsync(address))
        {
            var fileName = TryGetFileNameFromHeaders(client);
            if (string.IsNullOrWhiteSpace(fileName))
                fileName = defaultFileName;

            filePath = Path.Combine(directory, fileName);
            await WriteStreamToFile(stream, filePath);
        }

        return filePath;
    }

    private static string TryGetFileNameFromHeaders(WebClient client)
    {
        // content-disposition might contain the suggested file name, typically same as origiinal name on the server
        // Originally content-disposition is for email attachments, but web servers also use it.
        string contentDisposition = client.ResponseHeaders["content-disposition"];
        return string.IsNullOrWhiteSpace(contentDisposition) ?
            null :
            new ContentDisposition(contentDisposition).FileName;
    }

    private static async Task WriteStreamToFile(Stream stream, string filePath)
    {
        // Code below will throw generously, e. g. when we don't have write access, or run out of disk space
        using (var outStream = new FileStream(filePath, FileMode.CreateNew))
        {
            var buffer = new byte[8192];
            while (true)
            {
                int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
                if (bytesRead == 0)
                    break;
                // Could use async variant here as well. Probably helpful when downloading to a slow network share or tape. Not my use case.
                outStream.Write(buffer, 0, bytesRead);
            }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...