DotNetZip 将自解压器直接保存到 Response.OutputStream

DotNetZip save self-extractor directly to Response.OutputStream

我正在创建一个 REST 端点,它应该 return 一个 sfx(自解压存档)。我正在使用 Ionic.Zip 来完成创建实际存档的繁重工作,但我在理解如何将完成的 sfx 存档写回客户端时遇到了一些麻烦。

据我所知,ZipFile.Save(Response.OutputStream) 可以很好地写回 zip 文件,我很惊讶我不能使用 ZipFile.SaveSelfExtractor(Response.OutputStream, options) 之类的东西来做同样的事情。根据 docs,接收流的 SaveSelfExtractor 没有重载。

我可以在网上找到的例子解释了

  1. 我如何才能 create my own stub 并先将其写回到流中,然后将 zip 存档写入同一流之上。
  2. 如何temporarily store the sfx on the server,然后使用 FileStream 将其写回客户端。

但我不需要也不想在服务器上临时存储 sfx 可执行文件,并且我不想创建自己的 sfx 存根。我很高兴使用 Ionic 包中已经提供的存根。

有没有办法让 Ionic.Zip.ZipFile 创建 sfx 并一次性写回 Response.OutputStream

这是我现在拥有的:

using System.IO;
using Ionic.Zip;
using System.Web.Http;
using Context = System.Web.HttpContext;

namespace MyCompany.web.Controllers
{
    [HttpGet]
    public void Export()
    {
        var response = Context.Current.Response;
        var stream = response.OutputStream;

        // Create the zip archive in memory
        using (var archive = new ZipFile())
        {
            archive.Comment = "Self extracting export";
            archive.CompressionLevel = Ionic.Zlib.CompressionLevel.BestCompression;

            using (var memoryStream = new MemoryStream())
            using (var streamWriter = new StreamWriter(memoryStream))
            {
                streamWriter.WriteLine("Hello World");
                archive.AddEntry("testfile.txt", memoryStream.ToArray());
            }

            // What I want is to write this to outputstream
            archive.SaveSelfExtractor(/*stream*/ "export.exe", new SelfExtractorSaveOptions
            {
                Flavor = SelfExtractorFlavor.ConsoleApplication,
                Quiet = true,
                ExtractExistingFile = ExtractExistingFileAction.OverwriteSilently,
                RemoveUnpackedFilesAfterExecute = false
            });
            /*archive.Save(stream); // This will write to outputstream */
        }

        response.AddHeader("Content-Disposition", "attachment; filename=export.exe");
        response.AddHeader("Content-Description", "File Transfer");
        response.AddHeader("Content-Transfer-Encoding", "binary");
        response.ContentType = "application/exe";

        response.Flush();
        response.Close();
        response.End();
    }
}
using (ZipFile zip = new ZipFile())
{
    //string DirPath = Application.StartupPath + @"\CSVfile\files" + DateTime.Now.ToString("yyMMdd");
    string DirPath = Server.MapPath("DoneCSV//" + ViewState["Filepath"]);
    string savepath = DirPath + "/" + ViewState["Filepath"] + "_" + DateTime.Now.ToString("yyMMdd") + ".zip";
    zip.AddDirectory(DirPath);
    zip.Save(savepath);
    //sendmail(savepath);
}

我将此张贴给后代。这是我能想到的最好的解决方案。欢迎其他人提供更好的解决方案。

    [HttpGet]
    public void Export()
    {
        var response = Context.Current.Response;
        var writeStream = response.OutputStream;

        var name      = "export.exe";

        // Create the zip archive in memory
        using (var archive = new Ionic.Zip.ZipFile())
        {
            archive.Comment = "Self extracting export";
            archive.CompressionLevel = Ionic.Zlib.CompressionLevel.BestCompression;

            using (var memoryStream = new MemoryStream())
            using (var streamWriter = new StreamWriter(memoryStream))
            {
                streamWriter.WriteLine("Hello World");
                streamWriter.Flush();
                archive.AddEntry("testfile.txt", memoryStream.ToArray());
            }

            // Write sfx file to temp folder on server
            archive.SaveSelfExtractor(name, new Ionic.Zip.SelfExtractorSaveOptions
            {
                Flavor = Ionic.Zip.SelfExtractorFlavor.ConsoleApplication,
                Quiet = true,
                DefaultExtractDirectory = "\temp",
                SfxExeWindowTitle = "Export",
                ExtractExistingFile = Ionic.Zip.ExtractExistingFileAction.OverwriteSilently,
                RemoveUnpackedFilesAfterExecute = false
            });

            // Read file back and output to response
            using (var fileStream = new FileStream(name, FileMode.Open))
            {
                byte[] buffer = new byte[4000];
                int n = 1;
                while (n != 0)
                {
                    n = fileStream.Read(buffer, 0, buffer.Length);
                    if (n != 0)
                        writeStream.Write(buffer, 0, n);
                }
            }

            // Delete the temporary file
            if (File.Exists(name))
            {
                try { File.Delete(name); }
                catch (System.IO.IOException exc1)
                {
                    Debug.WriteLine("Warning: Could not delete file: {0} {1}", name, exc1);
                }
            }
        }

        response.AddHeader("Content-Disposition", "attachment; filename=" + name);
        response.AddHeader("Content-Description", "File Transfer");
        response.AddHeader("Content-Transfer-Encoding", "binary");
        response.ContentType = "application/exe";

        response.Flush();
        response.Close();
        response.End();
    }