【问题标题】:Return multiple files to download from asp.net返回多个文件以从 asp.net 下载
【发布时间】:2015-07-08 11:48:34
【问题描述】:

谁知道怎么做?我有一个循环,在那个循环中建立了一个列表。我希望每个列表都保存为具有不同文件名的不同文件(duh)。我为此使用 HttpContext.Current.Response 。单个文件工作正常,但是,我不能循环它。我在第二次迭代时收到的错误是“发送 HTTP 标头后服务器无法清除标头”。我的代码有点像下面。当然重要的是 // 对用户的响应所评论的部分。任何cmets都非常感谢!

欢呼, 罗纳德

        foreach (GridViewRow dr in GridView1.Rows)
        {
            // find the check box in the row
            System.Web.UI.WebControls.CheckBox cb = (System.Web.UI.WebControls.CheckBox)dr.FindControl("chkbx_selected");

            // see if it's checked
            if (cb != null && cb.Checked)
            {
                // get the cell
                DataControlFieldCell Cell = GetCellByName(dr, "GUID");
                string guid = new Guid(Cell.Text);

                // get the record filtered on the GUID
                var result_json = call_WEBAPI(guid);

                // result_json contains serialized List<string>
                List<string> result = JsonConvert.DeserializeObject<List<string>>(result_json);

                // response to user
                string filename = result[0] + ".txt";
                HttpContext.Current.Response.Clear();
                HttpContext.Current.Response.ClearHeaders();
                HttpContext.Current.Response.AppendHeader("content-disposition", string.Format("attachment; filename={0}", filename));
                HttpContext.Current.Response.ContentType = "application/octet-stream";
                foreach (string line in result)
                {
                    HttpContext.Current.Response.Write(line + Environment.NewLine);
                }

                HttpContext.Current.Response.Flush();

            }
        }

        HttpContext.Current.Response.End();

更新:我现在在内存中创建一个 zip 存档,创建一个条目并用一个 writer 填充它。但是如何在 .zip 中创建第二个条目?下面的代码不起作用,错误是“创建模式下的条目只能写入一次,一次只能打开一个条目。”

        using (MemoryStream zipToOpen = new MemoryStream())
        {
            using (ZipArchive archive = new ZipArchive(zipToOpen, ZipArchiveMode.Create, true))
            {
                ZipArchiveEntry readmeEntry = archive.CreateEntry("Readme.txt");
                using (StreamWriter writer = new StreamWriter(readmeEntry.Open()))
                {
                    writer.WriteLine("Information about this package.");
                    writer.WriteLine("========================");
                }

                List<string> result = new List<string>();

                result.Add("line1");
                result.Add("line2");

                ZipArchiveEntry readmeEntry2 = archive.CreateEntry("Readme2.txt");
                using (StreamWriter writer = new StreamWriter(readmeEntry.Open()))
                {
                    writer.Write(result);
                }

            }

            using (var fileStream = new FileStream(@"C:\test.zip", FileMode.Create))
            {
                zipToOpen.Seek(0, SeekOrigin.Begin);
                zipToOpen.CopyTo(fileStream);
            }
        }

【问题讨论】:

  • 如果您愿意,可以按照 jquery stackoverflow.com/questions/9047645/… 的演练进行操作
  • 我对jquery一无所知。通常我只在 API 后端工作,但我需要一个简单的 GUI。但是我可以尝试使用该帖子,谢谢。

标签: c# asp.net asp.net-mvc-4


【解决方案1】:

单个响应只能包含一个“文件”。 (从技术上讲,HTTP 没有“文件”的概念,这就是为什么会出现这种情况。HTTP 有“标头”和“内容”。正如错误告诉您的那样,一旦标头被发送,您就无法更改它们。因为它们已经发送给客户。)

您要么必须从多个请求/响应中返回文件,要么返回compress them into a single file and return that

(另外,为什么要将"application/octet-stream" 用于文本 文件?也许将其用于压缩文件,但文本文件可能应该是"text/plain" 或类似的东西。)

【讨论】:

  • 是的,我发现这应该是根本原因。但是如何通过单击 asp 页面上的一个按钮来生成多个请求/响应?我可以在这里使用Tasks orso(每个文件=一个线程)吗?并且“applications/octet-stream”强制浏览器保存文件而不是打开它们。
  • @Ronald:客户端必须发起后续请求,服务器不能对单个请求发送多个响应。所以你需要一些客户端代码来做到这一点。 zip 文件通常是更简单的解决方案。如果您想告诉客户端保存文件而不是显示它,这就是 Content-Disposition 标头的用途。您已经在使用。
  • 好的,谢谢,猜猜它会是 zip 变体。是不是像我描述的那样?后端文件的临时文件夹,压缩,然后发送压缩文件?我不能以某种方式在内存中做临时的东西并压缩它吗?
【解决方案2】:

您可以压缩服务器上的所有文件,然后发送一个 .zip 文件。正如谷歌所做的:) 它会解决你的问题

【讨论】:

  • 所以基本上创建一个临时目录,在那里转储文件,压缩临时目录并将其发送到 response.write 给最终用户?丑陋的恕我直言。
  • 您可以在内存中创建一个空的 zip,将文件放入其中并将其发送给用户。它会减小大小,并且您可以确定该文件可供用户下载,因为浏览器会阻止超过 1 个文件并询问用户是否允许下载多个文件
  • 好的,你有在内存中这样做的例子吗?我将在后端添加一个方法,然后将文件发送给用户下载。
  • 换句话说,在后端,我可以在内存中创建一个 zip 文件,在内存中创建其他文件,然后将这些最后的文件添加到内存中的 zip 文件中吗?然后将 zip 发送给调用的最终用户?它会适合内存,结果不会那么大。
  • 好的,我得到了这个工作,但是如何将第二个文件添加到存档中?请查看我的原始帖子,它的更新。
【解决方案3】:

当 zip 文件打开时,它总是打开的很烦人。! 但是,如果您尝试关闭,则只有一种方式处理,但这次是处理对象。 这就是解决方案处理并重新打开所有文件 就在一个开场示例的正下方

       string MappingpathZip = Path.Combine(HttpRuntime.AppDomainAppPath, @"XmlDocs\Invs\" + firmName + fileName + ".zip");
        ZipArchive zip = ZipFile.Open(MappingpathZip, ZipArchiveMode.Create);
        ZipArchiveEntry zae = zip.CreateEntryFromFile(MappingpathSignedXML, Path.GetFileName(MappingpathZip), CompressionLevel.Optimal);

        var stream = zae.Open();
        byte[] bytes;
        using (var ms = new MemoryStream())
        {
            stream.CopyTo(ms);
            bytes = ms.ToArray();
        }

【讨论】:

    猜你喜欢
    • 2011-08-15
    • 1970-01-01
    • 2022-06-22
    • 1970-01-01
    • 2012-12-18
    • 1970-01-01
    相关资源
    最近更新 更多