J4N
J4N

Reputation: 20761

Download a file in a specified stream?

I'm in an Asp.Net MVC web application.

For a specific action, I've to return a file generated from another internal server. This server require some credentials that web users doesn't own. So the Asp.net MVC server must connect itself to this server, download and send the downloaded file to the client.

Actually I'm doing it through an ActionResult:

public class ReportServerFileResult : FileResult
    {
        private readonly string _host;
        private readonly string _domain;
        private readonly string _userName;
        private readonly string _password;
        private readonly string _reportPath;
        private readonly Dictionary<string, string> _parameters;

        /// <summary>
        /// Initializes a new instance of the <see cref="ReportServerFileResult"/> class.
        /// </summary>
        /// <param name="contentType">Type of the content.</param>
        /// <param name="host">The host.</param>
        /// <param name="domain">The domain.</param>
        /// <param name="userName">Name of the user.</param>
        /// <param name="password">The password.</param>
        /// <param name="reportPath">The report path.</param>
        /// <param name="parameters">The parameters.</param>
        public ReportServerFileResult(string contentType, String host, String domain, String userName, String password, String reportPath, Dictionary<String, String> parameters)
            : base(contentType)
        {
            _host = host;
            _domain = domain;
            _userName = userName;
            _password = password;
            _reportPath = reportPath;
            _parameters = parameters;
        }

        #region Overrides of FileResult

        /// <summary>
        /// Writes the file to the response.
        /// </summary>
        /// <param name="response">The response.</param>
        protected override void WriteFile(HttpResponseBase response)
        {
            string reportUrl = String.Format("http://{0}{1}&rs:Command=Render&rs:Format=PDF&rc:Toolbar=False{2}",
                                             _host,
                                             _reportPath,
                                             String.Join("", _parameters.Select(p => "&" + p.Key + "=" + p.Value)));


            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(reportUrl);
            request.PreAuthenticate = true;
            request.Credentials = new NetworkCredential(_userName, _password, _domain);
            HttpWebResponse webResponse = (HttpWebResponse)request.GetResponse();
            Stream fStream = webResponse.GetResponseStream();
            webResponse.Close();

            fStream.CopyTo(response.OutputStream);
            fStream.Close();
        }

        #endregion
    }

But I don't like how stream are managed, because(if I've good correctly understood), we retrieve the full stream of the file and then starting to send it to the final user.

But it means that we are going to load the full file in memory, no?

So I was wondering if it is possible to give to the HttpWebRequest the stream in which it has to write the response? To stream directly the web response to the output?

Is it possible? Do you have another idea?

Upvotes: 0

Views: 403

Answers (1)

Anders Abel
Anders Abel

Reputation: 69280

You are already connecting the two streams. Just because you call GetResponse() will not read the entire data to memory.

The CopyTo() should read data from the source stream as needed, when the target stream can accept writing, depending on the transmission speed of the target stream.

Do you have any metrics that indicate that the entire content gets read into the memory of the web process?

Upvotes: 1

Related Questions