ASP.NET - response.outputstream.write 要么写入 16k,然后全为 0,要么每 64k 写入除 insetrs 之外的所有字符

标签 asp.net zip

我有以下代码...

public partial class DownloadFile : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        string FilePath = "[FTPPath]";
        Download downloadFile = new Download();
        Server.ScriptTimeout = 54000;

        try
        {
            long size = downloadFile.GetFileSize(FilePath);

            using (FtpWebResponse ftpResponse = downloadFile.BrowserDownload(FilePath))
            using (Stream streamResponse = ftpResponse.GetResponseStream())
            {
                string fileName = FilePath.Substring(FilePath.LastIndexOf("/") + 1);
                int bufferSize = 65536;
                byte[] buffer = new byte[bufferSize];
                int readCount;

                readCount = streamResponse.Read(buffer, 0, bufferSize);

                // Read file into buffer
                //streamResponse.Read(buffer, 0, (int)size);

                Response.Clear();
                Response.Buffer = false;
                Response.BufferOutput = false;

                //Apparently this line helps with old version of IE that like to cache stuff no matter how much you tell them!
                Response.AddHeader("Pragma", "public");

                //Expires: 0 forces the browser to always thing the page is "stale" therefore forcing it to never cache the page and therefore always re-downloads the page when viewed. Therefore no nasty experiences if we change the authentication details.
                Response.Expires = 0;

                //Again this line forces the browser not to cache the page.
                Response.AddHeader("Cache-Control", "no-cache, must-revalidate");
                Response.AddHeader("Cache-Control", "public");
                Response.AddHeader("Content-Description", "File Transfer");

                Response.ContentType = "application/zip";

                Response.AddHeader("Content-Disposition", "attachment; filename=" + fileName);
                Response.AddHeader("Content-Transfer-Encoding", "binary");
                Response.AddHeader("Content-Length", size.ToString());

                // writes buffer to OutputStream
                while (readCount > 0)
                {
                    Response.OutputStream.Write(buffer, 0, bufferSize);
                    readCount = streamResponse.Read(buffer, 0, bufferSize);
                    Response.Flush();
                }

                Response.End();
                Server.ScriptTimeout = 90;
            }
        }
        catch (Exception ex)
        {
            Response.Write("<p>" + ex.Message + "</p>");
            Server.ScriptTimeout = 90;
        }
    }
}

从 FTP 下载 .zip 文件(请忽略有关防止缓存的 header 垃圾,除非这与问题相关)。

所以 downloadFile 是我使用启用 SSL 的 FTPWebRequest/Response 编写的一个类,它可以做两件事;一种是返回 FTP 上文件的文件大小 (GetFileSize),另一种是设置 FtpWebRequest.Method = WebRequestMethods.Ftp.DownloadFile 以允许下载文件。

现在代码似乎可以完美运行,您会下载一个与 FTP 上的大小完全相同的精美 zip,但是,这就是怪癖开始的地方。

无论多小,zip 文件总是会损坏。理论上,非常小的文件应该没问题,但稍后您就会明白原因。因此,我决定比较二进制文件。

  • 如果我将 bufferSize 设置为文件大小以外的任何值 (即 1024、2048、65536),前 16k(16384 字节)下载 完美,然后流只是将零写入到末尾 文件。

  • 如果我设置 bufferSize = size(文件大小),则流似乎会下载完整的文件,直到您仔细观察。该文件在前 64k 之前都是精确的副本,然后下载的文件中会出现一个额外的字符(该字符似乎永远不会相同)。

    在这个额外的字节之后,文件再次完全相同。每 64k 似乎就会添加一个额外的字节,这意味着到 65MB 文件结束时,这两个文件严重不同步。由于下载长度受到服务器上文件大小的限制,因此下载文件中的文件末尾会被截断。当所有 CRC 检查失败时,存档将允许对其进行访问。

任何帮助将不胜感激。干杯。

现在稍微更改了我的代码,以使用 WebRequestWebResponse 从 Web 服务器本身使用 Http 获取 zip。这是代码...

public partial class DownloadFile : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{

    string FilePath = [http path];
    Server.ScriptTimeout = 54000;
    try
    {
        WebRequest HWR = WebRequest.Create(FilePath);
        HWR.Method = WebRequestMethods.File.DownloadFile;

        using (WebResponse FWR = HWR.GetResponse())
        using (BinaryReader streamResponse = new BinaryReader(FWR.GetResponseStream()))
        {
            string fileName = FilePath.Substring(FilePath.LastIndexOf("/") + 1);
            int bufferSize = 2048;
            byte[] buffer = new byte[bufferSize];
            int readCount;

            readCount = streamResponse.Read(buffer, 0, bufferSize);

            Response.Clear();
            Response.Buffer = false;
            Response.BufferOutput = false;
            //Apparently this line helps with old version of IE that like to cache stuff no matter how much you tell them!
            Response.AddHeader("Pragma", "public");
            //Expires: 0 forces the browser to always thing the page is "stale" therefore forcing it to never cache the page and therefore always re-downloads the page when viewed. Therefore no nasty experiences if we change the authentication details.
            Response.Expires = 0;
            //Again this line forces the browser not to cache the page.
            Response.AddHeader("Cache-Control", "no-cache, must-revalidate");
            Response.AddHeader("Cache-Control", "public");
            Response.AddHeader("Content-Description", "File Transfer");
            Response.ContentType = "application/zip";
            Response.AddHeader("Content-Disposition", "attachment; filename=" + fileName);
            Response.AddHeader("Content-Transfer-Encoding", "binary");

            // writes buffer to OutputStream
            while (readCount > 0)
            {
                Response.OutputStream.Write(buffer, 0, bufferSize);
                Response.Flush();
                readCount = streamResponse.Read(buffer, 0, bufferSize);
            }

            //Response.Write(testString);
            Response.End();
            Server.ScriptTimeout = 90;

        }
    }
    catch (Exception ex)
    {
        Response.Write("<p>" + ex.Message + "</p>");
        Server.ScriptTimeout = 90;
    }
}
}

这段代码更简单,但它仍然会破坏数据。我确信我做错了一些非常简单的事情,但我就是找不到它或找到一个测试来告诉我哪里出错了。请帮忙:)

最佳答案

在线

Response.OutputStream.Write(buffer, 0, bufferSize); 

将 bufferSize 更改为 readCount,以便您只写入实际读取的数字。

关于ASP.NET - response.outputstream.write 要么写入 16k,然后全为 0,要么每 64k 写入除 insetrs 之外的所有字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8168660/

相关文章:

javascript - 防止 javascript 代码在 asp.net 中转义

c# - ASP.NET 引用问题中的 MySQL 连接

zip - 我们如何估计压缩文件的 “overhead”?

python - 在 Python 中将 zip 列表保存到 csv

zip - Zip64 'end of central directory locator' 的目的是什么?

php - 防止在达到最小高度或粘贴文本时创建新的 div

c# - 使用 XML 文件绑定(bind)下拉列表

c# - 网站-编译类-在服务器中更新

c# - MSDeploy 无法手动部署压缩包

android - 在 Android 中打开受密码保护的 ZIP?