代码之家  ›  专栏  ›  技术社区  ›  Stephen Fischer

以.NET客户端连接时间传输文件?

  •  0
  • Stephen Fischer  · 技术社区  · 14 年前

    所以我问了一个关于使用C保护下载安全的问题。#( Securing Large Downloads Using C# and IIS 7 )我得到了一些关于如何做它的很好的建议(包括将文件读取到内存中,然后将其写入用户)。唯一的问题是,现在我正试图实现一些基本的日志记录,我撞上了一堵砖墙。以下是流式处理文件的代码:

    public void StreamFile(string file_path)
    {
        DateTime start;
        TimeSpan ts;
        FileStream fstream;
        string filename = Path.GetFileName(file_path);
        byte[] buffer = new byte[STREAM_BUFFER_SIZE];
        int count = 1, total = 0, seconds;
    
        // Open the file to read
        fstream = new FileStream("D:\\" + file_path, FileMode.Open, FileAccess.Read);
    
        // Set up the response headers
        Response.AddHeader("Content-Length", fstream.Length.ToString());
        Response.AddHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
        Response.ContentType = "application/octet-stream";
    
        // If the user agent is Internet Explorer, we add one last header
        if (Request.UserAgent.Contains("MSIE"))
            Response.AddHeader("Content-Transfer-Encoding", "binary");
    
        // Start counting the time
        start = DateTime.Now;
    
        // Now, until the client disconnects, we stream the file
        while (Response.IsClientConnected)
        {
            // Read the file into the buffer
            count = fstream.Read(buffer, 0, buffer.Length);
    
            // If the buffer is empty, break out of the loop. We're done!
            if (count == 0)
                break;
    
            // Write to the output stream and push it to the user
            Response.OutputStream.Write(buffer, 0, count);
            Response.Flush();
    
            // Increment the total as well, this way we can know how much we've streamed
            total += count;
        }
        // The transfer is done! Close the connection.
        Response.Close();
    
        // Count the number of seconds
        ts = DateTime.Now - start;
        seconds = ts.Seconds + (60 * ts.Minutes) + (60 * 60 * ts.Hours); // Also, is there a better way to do this? This is laaaaaame!
    
        // Finally, log the transfer
        Logging.AddLog(Request["user"], file_path, total, count == 0, seconds);
    }
    

    好的,所以问题是,这个创建的日志条目表明文件是在将文件读取到内存所用的秒数内完成的,而不是用户下载的。我认为这应该是客户的反应,但显然不是。所以日志报告的文件下载时间是0-1秒,即使我中途停止下载,日志也说它提供了整个过程。

    以前有人做过类似的事情,或者有什么想法可以让我在转账后得到实数?不幸的是,拥有这些信息是一个巨大的优先事项,或者我只是对它不屑一顾,将这两个值从日志中全部删除。

    2 回复  |  直到 14 年前
        1
  •  1
  •   Daniel A.A. Pelsmaeker    14 年前

    很抱歉,但你可能不可能做你想做的事。你打电话之后 Write () NetworkStream ),数据立即发送到Windows的套接字,后者将数据写入网卡的缓冲区。因此,.NET不会立即执行任何缓冲和写返回。因为.NET不缓冲NetworkStream,所以调用 Flush ()无效。因此,从.NET不可能等到数据离开网卡的缓冲区。

        2
  •  0
  •   MikeP    14 年前

    解决方案是让您的客户机应用程序在拥有整个文件后发送一个“已接收”的确认包。一旦你接收到它,你就知道它们实际上接收到了整个东西,并且可以停止计时器。