C# 将多个文件(具有不同的文件类型)从数据库(字节数组)导出到单个压缩文件

C# 将多个文件(具有不同的文件类型)从数据库(字节数组)导出到单个压缩文件,c#,asp.net,memorystream,C#,Asp.net,Memorystream,我需要导出存储在数据库(字节数组)中的不同文件类型(pdf、xlsx、docx)的多个文件,并将它们保存为单个压缩文件。我应该如何处理多个文件?我假设我首先需要将文件存储在一个列表中并使用MemoryStream?我正在使用ZipArchive类将文件导出为zip文件。假设这种方法可行,我不确定如何将列表作为参数传递给ZipArchive(DownloadMultipleFiles)方法 调用存储过程以获取文件并将其放置在列表中: public List<ZipList> GetFi

我需要导出存储在数据库(字节数组)中的不同文件类型(pdf、xlsx、docx)的多个文件,并将它们保存为单个压缩文件。我应该如何处理多个文件?我假设我首先需要将文件存储在一个列表中并使用MemoryStream?我正在使用ZipArchive类将文件导出为zip文件。假设这种方法可行,我不确定如何将列表作为参数传递给ZipArchive(DownloadMultipleFiles)方法

调用存储过程以获取文件并将其放置在列表中:

public List<ZipList> GetFilesandConvertToList(string applicationID)
{           
    List<ZipList> fileList = new List<ZipList>();
    SqlCommand cmd = new SqlCommand("dbo.spGetFilesByID", ConnC.con);
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.AddWithValue("@ApplicationID", applicationID); //This will return several files (different file types using the ID)
    ConnC.con.Open();
    using (SqlDataReader sdr = cmd.ExecuteReader())
    {
        if (sdr.HasRows)
        {
            while(sdr.Read())
            {
                ZipList zl = new ZipList();
                sdr.Read();
                zl.bytes = (byte[])sdr["FILE_CONTENT"];
                zl.contentType = sdr["FILE_TYPE"].ToString();
                zl.fileName = sdr["FILE_NAME"].ToString();
                fileList.Add(zl);
            }                    
         }
    }
    return fileList;
}
使用@Andy建议的方法将文件放入内存流并返回字节数组:

public byte[] GetZipFileForApplicationId(string applicationID)
{
    byte[] fileBytes = null;
    SqlCommand cmd = new SqlCommand("dbo.spGetFilesByID", ConnC.con);
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.AddWithValue("@ApplicationID", applicationID);
    ConnC.con.Open();
    using (SqlDataReader sdr = cmd.ExecuteReader())
    {
        if (sdr.HasRows)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                using (ZipArchive archive = new ZipArchive(ms, ZipArchiveMode.Create, true))
                {
                    while (sdr.Read())
                    {
                        byte[] bytes = (byte[])sdr["FILE_CONTENT"];
                        string contentType = sdr["FILE_TYPE"].ToString();
                        string fileName = sdr["FILE_NAME"].ToString();

                        ZipArchiveEntry entry = archive.CreateEntry(fileName);
                        using (Stream zipStream = entry.Open())
                        {
                            zipStream.Write(bytes, 0, bytes.Length);
                        }
                    }
                }
                ms.Position = 0;
                fileBytes = ms.ToArray();

            }
        }
    }
    return fileBytes;
}

看起来你大部分时间都在那里,事实上我认为你需要使用
List
,因为你的
byteArrayList
不包含文件名
Length`的定义

public void DownloadMultipleFiles(List<ZipList> zipList)
{
    using (MemoryStream ms = new MemoryStream())
    {
        using (ZipArchive archive = new ZipArchive(ms, ZipArchiveMode.Create, true))
        {
            foreach (var file in zipList)
            {
                ZipArchiveEntry entry = archive.CreateEntry(file.fileName + ".pdf", CompressionLevel.Fastest);
                using (Stream zipStream = entry.Open())
                {
                    zipStream.Write(file.bytes, 0, file.bytes.Length);
                }
            }
        }
        // Currently method returns void?
        // return File(ms.ToArray(), "application/zip", "Archive.zip");
        // Maybe you want
        File.WriteAllBytes("application/zip/Archive.zip", ms.ToArray());
    }
}
public void下载多文件(列表zipList)
{
使用(MemoryStream ms=new MemoryStream())
{
使用(ZipArchive archive=new ZipArchive(ms,ZipArchiveMode.Create,true))
{
foreach(zipList中的var文件)
{
ZipArchiveEntry entry=archive.CreateEntry(file.fileName+“.pdf”,CompressionLevel.faster);
使用(Stream zipStream=entry.Open())
{
写入(file.bytes,0,file.bytes.Length);
}
}
}
//当前方法返回void?
//返回文件(ms.ToArray(),“application/zip”,“Archive.zip”);
//也许你想要
writealBytes(“application/zip/Archive.zip”,ms.ToArray());
}
}

看起来您大部分时间都在,事实上我认为您需要使用
列表
,因为您的
byteArrayList
不包含文件名
长度的定义

public void DownloadMultipleFiles(List<ZipList> zipList)
{
    using (MemoryStream ms = new MemoryStream())
    {
        using (ZipArchive archive = new ZipArchive(ms, ZipArchiveMode.Create, true))
        {
            foreach (var file in zipList)
            {
                ZipArchiveEntry entry = archive.CreateEntry(file.fileName + ".pdf", CompressionLevel.Fastest);
                using (Stream zipStream = entry.Open())
                {
                    zipStream.Write(file.bytes, 0, file.bytes.Length);
                }
            }
        }
        // Currently method returns void?
        // return File(ms.ToArray(), "application/zip", "Archive.zip");
        // Maybe you want
        File.WriteAllBytes("application/zip/Archive.zip", ms.ToArray());
    }
}
public void下载多文件(列表zipList)
{
使用(MemoryStream ms=new MemoryStream())
{
使用(ZipArchive archive=new ZipArchive(ms,ZipArchiveMode.Create,true))
{
foreach(zipList中的var文件)
{
ZipArchiveEntry entry=archive.CreateEntry(file.fileName+“.pdf”,CompressionLevel.faster);
使用(Stream zipStream=entry.Open())
{
写入(file.bytes,0,file.bytes.Length);
}
}
}
//当前方法返回void?
//返回文件(ms.ToArray(),“application/zip”,“Archive.zip”);
//也许你想要
writealBytes(“application/zip/Archive.zip”,ms.ToArray());
}
}

你可以一箭双雕,不需要额外的模型就可以一次完成(这还没有经过测试,但你会得到要点):


你可以一石二鸟,不需要额外的模型就可以一次完成(这还没有经过测试,但你会得到要点):


@DaleK当我尝试下载多文件(列表)时
I get
…是一种类型,在给定上下文中无效。
我已将您的问题重新编辑,以包含其原始内容,否则提供的答案将毫无意义。在这个网站上,你需要问一个明确的问题,然后不要在人们发布答案后再从根本上改变它。如果你想向我们展示你最终使用的代码,请发布你自己的答案,因为未来的读者仍然清楚问题本身是什么以及可能的答案是什么。您也不应该将问题用作调试会话,如果您还有其他问题,请再问另一个问题。@DaleK当我尝试
下载multiplefiles(List)时
I get
…是一种类型,在给定上下文中无效。
我已将您的问题重新编辑,以包含其原始内容,否则提供的答案将毫无意义。在这个网站上,你需要问一个明确的问题,然后不要在人们发布答案后再从根本上改变它。如果你想向我们展示你最终使用的代码,请发布你自己的答案,因为未来的读者仍然清楚问题本身是什么以及可能的答案是什么。您也不应该将问题用作调试会话,如果您有其他问题,请提出其他问题。这让我非常接近。使用您的示例(稍微修改-参见我的原始帖子),我将如何返回字节以下载文件?@Shane--看看所有的答案:一些小修改修复了它(我更新了我的原始帖子)。谢谢,效果很好@谢恩,干得好。我喜欢一个计划的结合,这让我非常接近。使用您的示例(稍微修改-参见我的原始帖子),我将如何返回字节以下载文件?@Shane--看看所有的答案:一些小修改修复了它(我更新了我的原始帖子)。谢谢,效果很好@谢恩,干得好。我喜欢一份计划。这确实回答了我最初的一个问题,关于如何通过列表作为一个论据,然而,我修改了我原来的帖子,希望能澄清关于我要完成什么的困惑(返回一个压缩文件),并按照@Andy的建议去做(一石二鸟)。这确实回答了我最初的一个问题,关于如何将列表作为一个参数传递,但是,我修改了我的原始帖子,希望能够澄清我试图完成的工作(返回压缩文件)的困惑,并按照@Andy的建议去做(一石二鸟)。
public byte[] GetZipFileForApplicationId(string applicationID)
{
    byte[] fileBytes = null;
    SqlCommand cmd = new SqlCommand("dbo.spGetFilesByID", ConnC.con);
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.AddWithValue("@ApplicationID", applicationID);
    ConnC.con.Open();
    using (SqlDataReader sdr = cmd.ExecuteReader())
    {
        if (sdr.HasRows)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                using (ZipArchive archive = new ZipArchive(ms, ZipArchiveMode.Create, true))
                {
                    while (sdr.Read())
                    {
                        byte[] bytes = (byte[])sdr["FILE_CONTENT"];
                        string contentType = sdr["FILE_TYPE"].ToString();
                        string fileName = sdr["FILE_NAME"].ToString();

                        ZipArchiveEntry entry = archive.CreateEntry(fileName);
                        using (Stream zipStream = entry.Open())
                        {
                            zipStream.Write(bytes, 0, bytes.Length);
                        }
                    }
                }
                ms.Position = 0;
                fileBytes = ms.ToArray();

            }
        }
    }
    return fileBytes;
}
public void DownloadMultipleFiles(List<ZipList> zipList)
{
    using (MemoryStream ms = new MemoryStream())
    {
        using (ZipArchive archive = new ZipArchive(ms, ZipArchiveMode.Create, true))
        {
            foreach (var file in zipList)
            {
                ZipArchiveEntry entry = archive.CreateEntry(file.fileName + ".pdf", CompressionLevel.Fastest);
                using (Stream zipStream = entry.Open())
                {
                    zipStream.Write(file.bytes, 0, file.bytes.Length);
                }
            }
        }
        // Currently method returns void?
        // return File(ms.ToArray(), "application/zip", "Archive.zip");
        // Maybe you want
        File.WriteAllBytes("application/zip/Archive.zip", ms.ToArray());
    }
}
public byte[] GetZipFileForApplicationId(string applicationID)
{
    SqlCommand cmd = new SqlCommand("dbo.spGetFilesByID", ConnC.con);
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.AddWithValue("@ApplicationID", applicationID);
    ConnC.con.Open();
    using (SqlDataReader sdr = cmd.ExecuteReader())
    {
        if (sdr.HasRows)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                using (var archive = new ZipArchive(ms, ZipArchiveMode.Create, true))
                {
                    while(sdr.Read())
                    {
                        var bytes = (byte[])sdr["FILE_CONTENT"];
                        var contentType = sdr["FILE_TYPE"].ToString();
                        var fileName = sdr["FILE_NAME"].ToString();
                        
                        var entry = archive.CreateEntry(fileName);
                        using (var zipStream = entry.Open())
                        {
                            zipStream.Write(bytes, 0, bytes.Length);
                        }
                    } 
                }
                ms.Position = 0;
                // This is kind of redundant. You should return the
                // MemoryStream object instead of duplicating it's data.
                // I'll let you play with that.
                return ms.ToArray();
            }
        }
    }
    return null;
}