Scarica / Stream file da URL – asp.net

Devo eseguire lo streaming di un file che comporterà il salvataggio come richiesto nel browser. Il problema è che la directory in cui si trova il file è virtualmente mappata, quindi non riesco a utilizzare Server.MapPath per determinare la sua posizione effettiva. La directory non si trova nella stessa posizione (o anche server phyical nelle caselle live) come il sito web.

Mi piacerebbe qualcosa di simile al seguente, ma questo mi permetterà di passare un URL web, e non un percorso di file del server.

Potrei dover finire per build il mio percorso di file da un percorso di base di configurazione, e quindi aggiungere il resto del percorso, ma spero di poterlo fare in questo modo.

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

È ansible utilizzare HttpWebRequest per ottenere il file e inviarlo di nuovo al client. Questo ti permette di ottenere il file con un URL. Un esempio di ciò che ho trovato (ma non riesco a ricordare dove dare credito) lo è

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

Lo faccio un bel po ‘e ho pensato di aggiungere una risposta più semplice. L’ho impostato come semplice lezione qui, ma lo faccio ogni sera per raccogliere dati finanziari sulle aziende che sto seguendo.

 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 questo caso passo un URL e restituisce la pagina in formato HTML. Se vuoi fare qualcosa di diverso con lo stream, puoi facilmente cambiarlo.

Lo usi in questo modo:

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

Scarica l’url in byte e converti i byte nello stream:

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

2 anni dopo, ho usato la risposta di Dallas, ma ho dovuto modificare HttpWebRequest in FileWebRequest poiché stavo collegando ai file diretti. Non sono sicuro che sia così ovunque, ma ho pensato di aggiungerlo. Inoltre, ho rimosso

var resp = Http.Current.Resonse

e ha usato Http.Current.Response in qualsiasi posto in cui è stato fatto riferimento.

Puoi provare a utilizzare la class DirectoryEntry con il prefisso del percorso 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();