zoukankan      html  css  js  c++  java
  • ASP.NET 大文件下载

    一、ASP.NET 内建方案

      在WEB程序中下载一个文件,最简单有效的办法就是直接给个链接到该文件的虚拟路径,把所有的问题交给浏览器和WEB服务器去处理,但这种“良好”好的解决方案也会带来一些其它问题,譬如:无法在程序中控制下载权限,无法统计下载信息,无法将文件名更改为一个对客户良好的名字(事实上,为了避免服务器中文件名的重复,我们一般会分配给文件一个很长而又没有任何实际意义的名字,这不是客户端希望看到的,所以我们有必要在下载时重新为文件分配一个有意义的名字)。

    基于上述原因,ASP.NET提供了两个方法,用于在程序中接管服务器端文件的下载,它们是:

    • Response.WriteFile
    • Response.TransmitFile

    二、为什么不使用内建方案

      上面提到的两个内建方案有其致命的局限性。WriteFile 在获取文件的路径后,会试图将文件流全部读入内存,之后再发送回客户端。对于小文件和流量很小的网站,使用这个方法或许问题不大,但如果文件很大或者网站的流量很大,使用这个方法可以让 aspnet_wp.exe 进程意味终止,导致当前服务器下所有 asp.net 站点全部瘫痪,不仅如此,服务器的物理内存也会在瞬间被填满,导致其它程序运行失败或意外终止。TransmitFile 是 WriteFile 的一个改良版本,它解决了 WriteFile 将文件流一次性全部读入内存的错误举动,修改为按某个固定的字节循环读取,但它仍然存在问题,这个问题甚至比 WriteFile 的缺点更不能让人接受。使用 TransmitFile 下载文件,浏览器(IE)竟然不会弹出路径保存窗口,而是直接下载到临时目录,而对于IE的临时目录,或许很少有人能够快速准确地找到。

    三、替代方法

    要解决上面提到的问题,可以避免使用 WriteFile 和 TransmitFile 进行文件的读取,下面都是可行的替代方法:

    • 使用 FTP 传输文件
    • 直接提供一个指向文件的链接
    • 使用 Microsoft ASP 3.0 进行下载或者与 ASP 一起使用 Software Artisans FileUp
    • 创建 ISAPI 扩展以下载文件
    • 将数据分成较小的部分,然后将其移动到输出流以供下载,从而获取这些数据

    下面提供最后一种方法的 C# 源码

    System.IO.Stream iStream = null;

    // Buffer to read 10K bytes in chunk:
    byte[] buffer = new Byte[10000];

    // Length of the file:
    int length;

    // Total bytes to read:
    long dataToRead;

    // Identify the file to download including its path.
    string filepath = "DownloadFileName";

    // Identify the file name.
    string filename = System.IO.Path.GetFileName(filepath);

    try {
        
    // Open the file.
        iStream = new System.IO.FileStream(filepath, System.IO.FileMode.Open,
        System.IO.FileAccess.Read, System.IO.FileShare.Read);


        
    // Total bytes to read:
        dataToRead = iStream.Length;

        Response.ContentType 
    = "application/octet-stream";
        Response.AddHeader(
    "Content-Disposition""attachment; filename=" + filename);

        
    // Read the bytes.
        while (dataToRead > 0) {
            
    // Verify that the client is connected.
            if (Response.IsClientConnected) {
                
    // Read the data in buffer.
                length = iStream.Read(buffer, 010000);

                
    // Write the data to the current output stream.
                Response.OutputStream.Write(buffer, 0, length);

                
    // Flush the data to the HTML output.
                Response.Flush();

                buffer 
    = new Byte[10000];
                dataToRead 
    = dataToRead - length;
            } 
    else {
                
    //prevent infinite loop if user disconnects
                dataToRead = -1;
            }
        }
    catch (Exception ex) {
        
    // Trap the error, if any.
        Response.Write("Error : " + ex.Message);
    finally {
        
    if (iStream != null) {
            
    //Close the file.
            iStream.Close();
        }
    }

  • 相关阅读:
    The Python Standard Library
    Python 中的round函数
    Python文件类型
    Python中import的用法
    Python Symbols 各种符号
    python 一行写多个语句
    免费SSL证书(https网站)申请,便宜SSL https证书申请
    元宇宙游戏Axie龙头axs分析
    OLE DB provider "SQLNCLI10" for linked server "x.x.x.x" returned message "No transaction is active.".
    The operation could not be performed because OLE DB provider "SQLNCLI10" for linked server "xxx.xxx.xxx.xxx" was unable to begin a distributed transaction.
  • 原文地址:https://www.cnblogs.com/wfyfngu/p/1340773.html
Copyright © 2011-2022 走看看