简体   繁体   English

通过我的服务器将文件从远程服务器复制到客户端浏览器,而无需将整个文件写入磁盘或内存

[英]Copy file from remote server to client browser via my server without writing the entire file to disk or memory

This is the scenario. 这是方案。

There is a file on a remote file server (say I have a file hosted on DropBox) 远程文件服务器上有一个文件(例如,我在DropBox上托管了一个文件)

I want to offer that file as a download on my web application (c# asp.net 4.0) 我想在我的Web应用程序(c#asp.net 4.0)上提供该文件作为下载。

I want to hide the location 100% of the original file (I want it to appear to come from my sever). 我想隐藏原始文件100%的位置(我希望它看起来像是来自我的服务器)。

I do not want to write this file to memory or to disk on my server. 我不想将此文件写入服务器上的内存或磁盘。

I had assumed that I would want to use a stream to stream copy. 我以为我想使用流来流复制。 example

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

inputStream.Flush();

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

This however copies the entire stream into memory before writing it out to the client browser. 但是,这会将整个流复制到内存中,然后再将其写到客户端浏览器。 Any ideas would be awesome. 任何想法都很棒。

I need my server to basically just act as a proxy and shield the original file location 我需要服务器基本上只是充当代理并屏蔽原始文件位置

Thanks for any help. 谢谢你的帮助。

The following code is what I ended up with (the buffer size will change in production) This gets a file from a url, and starts streaming it chunk by chunk to a client through my server. 下面的代码是我最终得到的结果(缓冲区的大小将在生产中改变)这将从URL获取文件,并开始通过服务器将其逐块流式传输到客户端。 The part that took me a bit to figure out was flushing the Response after each chunk was written. 我花了点时间才知道的部分是在写入每个块之后刷新响应。

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

This can stream any size file through my server without waiting for my server to fist store it into memory or onto disk. 这可以通过服务器流式传输任何大小的文件,而无需等待服务器将其首先存储到内存或磁盘上。 The real advantage is that it uses very little memory as only the buffered chunk is stored. 真正的优势在于它只使用很少的内存,因为仅存储了缓冲的块。 To the client the downloads begins instantly. 对于客户端,下载立即开始。 (this is probably obvious to most but was very cool for this novice to see) so we are simultaneously downloading the file from one location and uploading it to another using the server as a sort of proxy. (这对大多数人来说可能是显而易见的,但对于新手来说很酷),因此我们同时从一个位置下载文件,然后使用服务器作为代理将其上传到另一个位置。

While I don't see reasons why CopyTo will read whole stream in memory (as there is no intermediate stream anywhere), you can write the same Copy manually to be sure it behaves the way you want. 虽然我看不到CopyTo为何会读取内存中的整个流的原因(因为任何地方都没有中间流),但是您可以手动编写相同的Copy以确保其行为符合您的期望。

Consider using Async versions of read/write and if you can use async / awit from C# 4.0 to make code readable. 考虑使用异步版本的读/写,以及是否可以使用C#4.0中的async / awit使代码可读。

Old way: Asynchronous Stream Processing , new ways Asynchronous File I/O 旧方法: 异步流处理 ,新方法异步文件I / O

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM