【问题标题】:Copy file from remote server to client browser via my server without writing the entire file to disk or memory通过我的服务器将文件从远程服务器复制到客户端浏览器,而无需将整个文件写入磁盘或内存
【发布时间】:2013-03-28 09:46:49
【问题描述】:

这就是场景。

远程文件服务器上有一个文件(比如我有一个托管在 DropBox 上的文件)

我想在我的 Web 应用程序 (c# asp.net 4.0) 上下载该文件

我想 100% 隐藏原始文件的位置(我希望它看起来来自我的服务器)。

我不想将此文件写入内存或服务器上的磁盘。

我曾假设我想使用流来流式复制。例子

Stream inputStream = response.GetResponseStream();
inputStream.CopyTo(Response.OutputStream, 4096);

inputStream.Flush();

Response.Flush();
Response.End();

但是,这会将整个流复制到内存中,然后再将其写入客户端浏览器。任何想法都会很棒。

我需要我的服务器基本上只是充当代理并屏蔽原始文件位置

感谢您的帮助。

【问题讨论】:

  • 你不能只是混淆网址。没有办法做到这一点,可以很好地扩展。
  • @bumble_bee_tuna,代理服务器可以很好地扩展——尤其是在无状态的情况下——只需根据需要添加任意数量的服务器。

标签: c# stream filestream getresponsestream responsestream


【解决方案1】:

以下代码是我最终得到的(缓冲区大小会在生产中改变) 这从 url 获取文件,并开始通过我的服务器将其逐块流式传输到客户端。我花了一点时间才弄清楚的部分是在写入每个块后刷新响应。

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(digitalAsset.FullFilePath);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            if (response.StatusCode == HttpStatusCode.OK)
            {
                Response.ClearHeaders();
                Response.ClearContent();
                Response.Clear();
                Response.ContentType = "application/octet-stream";
                Response.AddHeader("Content-Disposition", "attachment;filename=" +     digitalAsset.FileName);

                Stream inputStream = response.GetResponseStream();

                byte[] buffer = new byte[512];
                int read;
                while ((read = inputStream.Read(buffer, 0, buffer.Length)) > 0)
                {
                    Response.OutputStream.Write(buffer, 0, read);
                    Response.Flush();
                }
                Response.End();
            }

这可以通过我的服务器流式传输任何大小的文件,而无需等待我的服务器将其存储到内存或磁盘中。真正的优势是它使用的内存非常少,因为只存储了缓冲的块。对于客户端,下载立即开始。 (这对大多数人来说可能很明显,但对于这个新手来说非常酷)所以我们同时从一个位置下载文件并使用服务器作为一种代理将其上传到另一个位置。

【讨论】:

    【解决方案2】:

    虽然我不明白为什么 CopyTo 会读取内存中的整个流(因为任何地方都没有中间流),但您可以手动编写相同的 Copy 以确保其行为符合您的要求。

    考虑使用异步版本的读/写,以及是否可以使用 C# 4.0 中的 async/awit 使代码可读。

    旧方式:Asynchronous Stream Processing,新方式Asynchronous File I/O

    【讨论】:

    • 这是一个很大的帮助。我将用完成的代码进行回复,以防其他人需要这样做。
    • CopyTo 不是问题所在。嗯,有点。事实上,在整个流被写入之前,Response 对象没有被刷新。我必须从头开始创建该方法,以便在每个块之后添加刷新 Stream。
    猜你喜欢
    • 2018-01-09
    • 2020-03-31
    • 1970-01-01
    • 2019-01-20
    • 1970-01-01
    • 2020-07-20
    • 2018-05-24
    • 1970-01-01
    • 2015-06-25
    相关资源
    最近更新 更多