Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/41.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从URL-asp.net下载/流式传输文件_C#_Asp.net_File Io_Streaming - Fatal编程技术网

C# 从URL-asp.net下载/流式传输文件

C# 从URL-asp.net下载/流式传输文件,c#,asp.net,file-io,streaming,C#,Asp.net,File Io,Streaming,我需要流一个文件,这将导致在浏览器中的另存为提示。 问题是,文件所在的目录实际上已映射,因此我无法使用Server.MapPath确定其实际位置。该目录与网站不在同一位置(甚至不在live Box上的phyical服务器) 我希望类似于以下内容,但这将允许我传递一个web URL,而不是服务器文件路径 我可能不得不从配置基路径构建文件路径,然后附加到路径的其余部分,但希望我可以用这种方式来代替 var filePath = Server.MapPath(DOCUMENT_PATH); if (

我需要流一个文件,这将导致在浏览器中的另存为提示。 问题是,文件所在的目录实际上已映射,因此我无法使用Server.MapPath确定其实际位置。该目录与网站不在同一位置(甚至不在live Box上的phyical服务器)

我希望类似于以下内容,但这将允许我传递一个web URL,而不是服务器文件路径

我可能不得不从配置基路径构建文件路径,然后附加到路径的其余部分,但希望我可以用这种方式来代替

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

您可以尝试使用具有IIS路径前缀的DirectoryEntry类:

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

您可以使用HttpWebRequest获取文件并将其流式传输回客户端。这允许您使用url获取文件。我发现的一个例子是(但记不起在哪里给信用)


2年后,我使用了达拉斯的答案,但我不得不将
HttpWebRequest
更改为
FileWebRequest
,因为我链接到了直接文件。不确定是否所有地方都是这样,但我想我应该加上它。而且,我删除了

var resp=Http.Current.Resonse


只要在引用
resp
的地方使用
Http.Current.Response

我经常这样做,我想我可以添加一个更简单的答案。我在这里设置了一个简单的课程,但是我每天晚上都运行这个课程来收集我关注的公司的财务数据

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;
    }
}
在本例中,我传入一个url,它以HTML的形式返回页面。如果你想对流做一些不同的事情,你可以很容易地改变它

您可以这样使用它:

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

将url下载到字节并将字节转换为流:

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

如果我们在Citrix Netscaler上使用负载平衡器(没有WAF策略),达拉斯认可的解决方案对我们有效

当文件与WAF关联时,文件的下载无法通过Netscaler的LB工作,因为当前场景(内容长度不正确)是RFC冲突,并且AppFW重置连接,而当WAF策略未关联时,不会发生这种情况

因此,缺少的是:

响应。结束()

另见:

如果您正在寻找@Dallas答案的.NET核心版本,请使用以下选项

        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(@"file 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.Response;

            //Indicate the type of data being sent
            resp.ContentType = "application/octet-stream";

            //Name the file 
            resp.Headers.Add("Content-Disposition", "attachment; filename=test.zip");
            resp.Headers.Add("Content-Length", fileResp.ContentLength.ToString());

            int length;
            do
            {
                // Verify that the client is connected.
                if (!HttpContext.RequestAborted.IsCancellationRequested)
                {
                    // Read data into the buffer.
                    length = stream.Read(buffer, 0, bytesToRead);

                    // and write it out to the response's output stream
                    resp.Body.Write(buffer, 0, length);


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

你能详细说明一下“虚拟映射”的含义吗?可通过URL访问的虚拟IIS文件夹?它使用VPP路径,这是EpiServer CMS使用的概念。我们设置虚拟路径名(即“/documents/”),然后指定该路径也应映射的物理路径(即“//servername/documents”)。然后,系统在运行时创建对目录的引用。您可以通过web URL浏览到文件,而无需发出任何问题。文件名确实可以通过URL访问。我需要使用此URL来流式传输文件,而不是服务器路径,因为我无法从URL(使用MapPath)中删除此URL。如果您知道URL,并且文件扩展名在浏览器中打开“另存为”提示(或者这是您的问题之一),也许您可以将请求重定向到要下载的文件?否则,user97970的建议似乎是可行的。每次运行时刷新响应和重新创建缓冲区都是不必要的——这只会减慢传输速度。另外,我认为应该重命名一些变量(fileReq->urlRequest,fileResp->urlResponse)。另外,没有理由创建Stream变量,在开始时,您应该在使用它的地方创建它(靠近GetResponseStream()调用)@data\u smith为什么不试试您的建议呢?它不会编译。缓冲区的作用是降低web服务器上的内存使用率。本例中未定义resp:代码未编译。正如@Sharon所述,此代码未编译。您需要做的是,在注释处读取
//准备对客户端的响应。resp是客户端响应,添加此代码位:
var resp=HttpContext.Current.Response@Dallas谢谢你的样品,它让我很开心。我在构建一个服务时使用它,该服务将mp3文件流式传输到Windows Phone 7客户端,其中AudioPlayerAgent无法处理重定向302,然后需要直接返回文件流。我的情况不同,有一个文档管理系统,以.tif格式返回文档,其中在querystring中发送no。但这种方法行不通,任何想法都值得赞赏。thanks@kayhanyüksel:我尝试了那个链接,但它超时了。对不起,太好了。我把达拉的答案删掉了一点。我在下面发布了我的版本,虽然这看起来很简单,工作也很好,但是你需要记住,这个解决方案会将文件加载到你的计算机内存中。因此,当1)一个数据太大或2)同时发出多个请求时,由于内存不足而导致异常的可能性很高。Benjamin,这个问题可以通过使用来缓解。
        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(@"file 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.Response;

            //Indicate the type of data being sent
            resp.ContentType = "application/octet-stream";

            //Name the file 
            resp.Headers.Add("Content-Disposition", "attachment; filename=test.zip");
            resp.Headers.Add("Content-Length", fileResp.ContentLength.ToString());

            int length;
            do
            {
                // Verify that the client is connected.
                if (!HttpContext.RequestAborted.IsCancellationRequested)
                {
                    // Read data into the buffer.
                    length = stream.Read(buffer, 0, bytesToRead);

                    // and write it out to the response's output stream
                    resp.Body.Write(buffer, 0, length);


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