Скачать / скачать файл с URL - asp.net - PullRequest
64 голосов
/ 08 апреля 2011

Мне нужно передать файл, который приведет к сохранению как приглашение в браузере. Проблема в том, что каталог, в котором находится файл, фактически сопоставлен, поэтому я не могу использовать Server.MapPath, чтобы определить его фактическое местоположение. Каталог не находится в том же месте (или даже на физическом сервере в живых коробках), что и веб-сайт.

Я бы хотел что-то вроде следующего, но это позволит мне передать веб-URL, а не путь к файлу сервера.

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

var filePath = Server.MapPath(DOCUMENT_PATH);

if (!File.Exists(filePath))
    return;

var fileInfo = new System.IO.FileInfo(filePath);
Response.ContentType = "application/octet-stream";
Response.AddHeader("Content-Disposition", String.Format("attachment;filename=\"{0}\"", filePath));
Response.AddHeader("Content-Length", fileInfo.Length.ToString());
Response.WriteFile(filePath);
Response.End();

Ответы [ 6 ]

94 голосов
/ 09 апреля 2011

Вы можете использовать HttpWebRequest, чтобы получить файл и отправить его обратно клиенту.Это позволяет вам получить файл с URL.Пример этого, который я нашел (но не могу вспомнить, где давать кредит):

    //Create a stream for the file
    Stream stream = null;

    //This controls how many bytes to read at a time and send to the client
    int bytesToRead = 10000;

    // Buffer to read bytes in chunk size specified above
    byte[] buffer = new Byte[bytesToRead];

    // The number of bytes read
    try
    {
      //Create a WebRequest to get the file
      HttpWebRequest fileReq = (HttpWebRequest) HttpWebRequest.Create(url);

      //Create a response for this request
      HttpWebResponse fileResp = (HttpWebResponse) fileReq.GetResponse();

      if (fileReq.ContentLength > 0)
        fileResp.ContentLength = fileReq.ContentLength;

        //Get the Stream returned from the response
        stream = fileResp.GetResponseStream();

        // prepare the response to the client. resp is the client Response
        var resp = HttpContext.Current.Response;

        //Indicate the type of data being sent
        resp.ContentType = "application/octet-stream";

        //Name the file 
        resp.AddHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
        resp.AddHeader("Content-Length", fileResp.ContentLength.ToString());

        int length;
        do
        {
            // Verify that the client is connected.
            if (resp.IsClientConnected)
            {
                // Read data into the buffer.
                length = stream.Read(buffer, 0, bytesToRead);

                // and write it out to the response's output stream
                resp.OutputStream.Write(buffer, 0, length);

                // Flush the data
                resp.Flush();

                //Clear the buffer
                buffer = new Byte[bytesToRead];
            }
            else
            {
                // cancel the download if client has disconnected
                length = -1;
            }
        } while (length > 0); //Repeat until no data is read
    }
    finally
    {
        if (stream != null)
        {
            //Close the input stream
            stream.Close();
        }
    }
17 голосов
/ 10 февраля 2016

Загрузка URL в байты и преобразование байтов в поток:

using (var client = new WebClient())
{
    var content = client.DownloadData(url);
    using (var stream = new MemoryStream(content))
    {
        ...
    }
}   
12 голосов
/ 02 июня 2015

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

class WebPage
{
    public static string Get(string uri)
    {
        string results = "N/A";

        try
        {
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uri);
            HttpWebResponse resp = (HttpWebResponse)req.GetResponse();

            StreamReader sr = new StreamReader(resp.GetResponseStream());
            results = sr.ReadToEnd();
            sr.Close();
        }
        catch (Exception ex)
        {
            results = ex.Message;
        }
        return results;
    }
}

В этом случае я передаю URL-адрес, и он возвращает страницу какHTML.Если вы хотите сделать что-то другое с потоком вместо этого, вы можете легко изменить это.

Вы используете это так:

string page = WebPage.Get("http://finance.yahoo.com/q?s=yhoo");
4 голосов
/ 11 ноября 2014

2 года спустя я использовал ответ Далласа, но мне пришлось изменить HttpWebRequest на FileWebRequest, так как я связывался с прямыми файлами.Не уверен, что так везде, но я решил добавить.Кроме того, я удалил

var resp = Http.Current.Resonse

и просто использовал Http.Current.Response на месте, где упоминалась resp.

0 голосов
/ 29 апреля 2019

Принятое нами решение от Далласа сработало для нас, если мы используем балансировщик нагрузки на Citrix Netscaler (без политики WAF).

Загрузка файла не работает через LB Netscaler, когда он связан с WAF, поскольку текущий сценарий (неверная длина содержимого) является нарушением RFC, и AppFW сбрасывает соединение, которое не происходит, когда политика WAF не связана.

Итак, чего не хватало, было:

Response.End ();

Смотрите также: Попытка потоковой передачи файла PDF с помощью asp.net приводит к «поврежденному файлу»

0 голосов
/ 08 апреля 2011

Можно попробовать использовать класс DirectoryEntry с префиксом пути IIS:

using(DirectoryEntry de = new DirectoryEntry("IIS://Localhost/w3svc/1/root" + DOCUMENT_PATH))
{
    filePath = de.Properties["Path"].Value;
}

if (!File.Exists(filePath))
        return;

var fileInfo = new System.IO.FileInfo(filePath);
Response.ContentType = "application/octet-stream";
Response.AddHeader("Content-Disposition", String.Format("attachment;filename=\"{0}\"", filePath));
Response.AddHeader("Content-Length", fileInfo.Length.ToString());
Response.WriteFile(filePath);
Response.End();
...