Descargar / Transmitir archivo desde la URL – asp.net

Necesito transmitir un archivo que dará como resultado guardarlo en el navegador. El problema es que el directorio donde se encuentra el archivo está prácticamente mapeado, por lo que no puedo usar Server.MapPath para determinar su ubicación real. El directorio no está en la misma ubicación (o incluso servidor físico en los cuadros activos) que el sitio web.

Me gustaría algo como lo siguiente, pero eso me permitirá pasar una URL web, y no una ruta de archivo de servidor.

Puede que tenga que terminar construyendo mi ruta de archivo desde una ruta base de configuración, y luego anexar en el rest de la ruta, pero espero poder hacerlo de esta manera.

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

Puede usar HttpWebRequest para obtener el archivo y transmitirlo nuevamente al cliente. Esto le permite obtener el archivo con una url. Un ejemplo de esto que encontré (pero no puedo recordar dónde dar crédito) es

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

Hago esto bastante y pensé que podría agregar una respuesta más simple. Lo configuré como una clase simple aquí, pero lo ejecuto todas las noches para recostackr datos financieros de las empresas que estoy siguiendo.

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

En este caso, paso una url y devuelve la página como HTML. Si quieres hacer algo diferente con la transmisión, puedes cambiar esto fácilmente.

Lo usas así:

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

Descarga url a bytes y convierte bytes en stream:

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

2 años después, utilicé la respuesta de Dallas, pero tuve que cambiar la HttpWebRequest a FileWebRequest porque estaba enlazando a archivos directos. No estoy seguro de si este es el caso en todas partes, pero pensé que lo agregaría. Además, quité

var resp = Http.Current.Resonse

y simplemente usé Http.Current.Response en el lugar donde se hizo referencia a resp .

Podría intentar usar la clase DirectoryEntry con el prefijo de ruta 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();