web-dev-qa-db-de.com

Datei von URL herunterladen / streamen - asp.net

Ich muss eine Datei streamen, die zum Speichern als Eingabeaufforderung im Browser führt. Das Problem ist, dass das Verzeichnis, in dem sich die Datei befindet, virtuell zugeordnet ist, sodass ich Server.MapPath nicht verwenden kann, um den tatsächlichen Speicherort zu bestimmen. Das Verzeichnis befindet sich nicht am selben Ort (oder sogar auf einem physischen Server in den Live-Boxen) wie die Website.

Ich hätte gerne Folgendes, aber damit kann ich eine Web-URL und keinen Server-Dateipfad übergeben.

Möglicherweise muss ich meinen Dateipfad aus einem Konfigurationsbasispfad erstellen und dann an den Rest des Pfads anhängen, aber hoffentlich kann ich es stattdessen auf diese Weise tun.

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();
65
mp3duck

Sie können HttpWebRequest verwenden, um die Datei abzurufen und an den Client zurückzusenden. Auf diese Weise können Sie die Datei mit einer URL abrufen. Ein Beispiel dafür, das ich gefunden habe (aber ich kann mich nicht erinnern, wo ich Kredit geben soll), ist

    //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();
        }
    }
95
Dallas

Laden Sie die URL in Bytes herunter und konvertieren Sie Bytes in Streams:

using (var client = new WebClient())
{
    var content = client.DownloadData(url);
    using (var stream = new MemoryStream(content))
    {
        ...
    }
}   
18
Berezh

Ich mache das ziemlich oft und dachte, ich könnte eine einfachere Antwort hinzufügen. Ich habe es hier als einfache Klasse eingerichtet, aber ich leite es jeden Abend, um Finanzdaten über Unternehmen zu sammeln, denen ich folge.

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;
    }
}

In diesem Fall übergebe ich eine URL und es wird die Seite als HTML zurückgegeben. Wenn Sie stattdessen etwas anderes mit dem Stream machen möchten, können Sie dies leicht ändern.

Du benutzt es so:

string page = WebPage.Get("http://finance.yahoo.com/q?s=yhoo");
12
CodeChops

2 Jahre später habe ich die Antwort von Dallas verwendet, aber ich musste HttpWebRequest in FileWebRequest ändern, da ich auf direkte Dateien verweise. Ich bin mir nicht sicher, ob dies überall der Fall ist, aber ich dachte, ich würde es hinzufügen. Auch ich habe entfernt

var resp = Http.Current.Resonse

und gerade verwendet Http.Current.Response überall dort, wo resp referenziert wurde.

4
Tingo

Die akzeptierte Lösung von Dallas hat für uns funktioniert, wenn wir Load Balancer auf dem Citrix Netscaler verwenden (ohne WAF-Richtlinie).

Der Download der Datei funktioniert nicht über die LB des Netscaler, wenn sie mit WAF verknüpft ist, da das aktuelle Szenario (Länge des Inhalts nicht korrekt) eine RFC-Verletzung darstellt und AppFW die Verbindung zurücksetzt, was bei WAF nicht der Fall ist Politik ist nicht zugeordnet.

Was also fehlte, war:

Response.End ();

Siehe auch: Der Versuch, eine PDF Datei mit asp.net zu streamen, erzeugt eine "beschädigte Datei"

0
Oliver Fink