web-dev-qa-db-fra.com

Télécharger / Diffuser un fichier à partir d'une URL - asp.net

J'ai besoin de diffuser un fichier qui entraînera une sauvegarde en tant qu'invite dans le navigateur. Le problème est que le répertoire dans lequel se trouve le fichier est virtuellement mappé. Je ne peux donc pas utiliser Server.MapPath pour déterminer son emplacement réel. Le répertoire ne se trouve pas au même emplacement (ni même sur les serveurs physiques des boîtiers actifs) que le site Web.

Je voudrais quelque chose comme ce qui suit, mais cela me permettra de transmettre une URL Web, et non un chemin de fichier du serveur.

Je vais peut-être devoir créer mon chemin de fichier à partir d'un chemin de base de configuration, puis l'ajouter au reste du chemin, mais j'espère pouvoir le faire de cette façon.

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

Vous pouvez utiliser HttpWebRequest pour obtenir le fichier et le retransmettre au client. Cela vous permet d’obtenir le fichier avec une URL. Un exemple de ceci que j'ai trouvé (mais ne me souviens pas où donner du crédit) est

    //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

Téléchargez l'URL en octets et convertissez-les en flux:

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

Je fais cela un peu et je pensais pouvoir ajouter une réponse plus simple. Je l’organise comme une simple classe ici, mais j’utilise cette technique tous les soirs pour collecter des données financières sur les entreprises que je suis.

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

Dans ce cas, je passe dans une URL et la page est renvoyée au format HTML. Si vous voulez faire quelque chose de différent avec le flux, vous pouvez facilement changer cela.

Vous l'utilisez comme ceci:

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

Deux ans plus tard, j'utilisais la réponse de Dallas, mais je devais changer le HttpWebRequest en FileWebRequest puisque je liais vers des fichiers directs. Pas sûr que ce soit le cas partout, mais je me suis dit que je l'ajouterais. Aussi, j'ai enlevé

var resp = Http.Current.Resonse

et juste utilisé Http.Current.Response _ en place partout où resp a été référencé.

4
Tingo

La solution acceptée par Dallas fonctionnait pour nous si nous utilisions Load Balancer sur Citrix Netscaler (sans stratégie WAF).

Le téléchargement du fichier ne fonctionne pas via le LB de Netscaler quand il est associé à WAF car le scénario actuel (Content-length n’est pas correct) est une violation RFC et AppFW réinitialise la connexion, ce qui n’est pas le cas lorsque WAF la politique n'est pas associée.

Donc ce qui manquait était:

Response.End ();

Voir aussi: Essayer de diffuser un PDF avec asp.net génère un "fichier endommagé"

0
Oliver Fink