最近做项目有一个这样的需求,导出列表上的数据,若勾选了多个则将所有数据导出文件打包到一个压缩包中导出,找了很多实现方式,最终实现的方式为:多个文件分别导出到指定文件夹,然后再将所有文件写入到压缩包中,最后再将所有文件删除掉,然后压缩包再以流的形式输出到浏览器,最后删除掉临时存放的压缩包文件,大概流程就是这样,下面具体讲解代码的实现过程:
1 public IActionResult ExportReceiveReport(string objectId)
2 {
3 string[] dataArr = objectId.Split(',');
4
5 bool isZip = false;
6 if (dataArr.Length > 1)
7 {
8 isZip = true;
9 }
10 List<string> fileList = new List<string>();
11 string savePath = AppDomain.CurrentDomain.BaseDirectory;
12 string templateFilePathName = _webHostEnvironment.WebRootPath + "//Template//ReceiveFile.xls";
13 System.IO.MemoryStream mStream = new MemoryStream();
14 string fixName = DateTime.Now.ToString("yyyyMMddHHmmss");
15 for (int i = 0; i < dataArr.Length; i++)
16 {
17 DataTable dt = ReportServices.GetReceiveReport(dataArr[i]);
18 dt.TableName = "Receive";
19 //下载
20 mStream = ReportServices.OutModelFileToStream(dt, templateFilePathName, "营收月报");
21 if (isZip)
22 {
23 string savePath2 = savePath + "Doc//";
24 if (!Directory.Exists(savePath2))//如果不存在就创建file文件夹
25 {
26 Directory.CreateDirectory(savePath2);
27 }
28 string FileNames = savePath2 + fixName + i + "营收月报.xls";
29 if (System.IO.File.Exists(FileNames))
30 {
31 System.IO.File.Delete(FileNames);
32 }
33
34 FileStream fs = new FileStream(FileNames, FileMode.Create, FileAccess.Write);
35 BinaryWriter w = new BinaryWriter(fs);
36 w.Write(mStream.ToArray());
37 fs.Close();
38 fs.Dispose();
39 mStream.Close();
40 fileList.Add(FileNames);
41 }
42 }
43 if (!isZip)
44 {
45 //客户端保存的文件名
46 string fileName = "营收月报" + fixName + ".xls";
47 return File(mStream.ToArray(), "application/vnd.ms-excel", fileName);
48 }
49 else
50 {
51 string saveZip = savePath + "Zip//";
52 if (!Directory.Exists(saveZip))//如果不存在就创建file文件夹
53 {
54 Directory.CreateDirectory(saveZip);
55 }
56 string fsUrl = saveZip + "营收月报.zip";
57
58 //压缩包里面写入文件
59 ZipHelper.ZipFile(fsUrl, fileList);
60 var fileInfo = new FileInfo(fsUrl);
61 MemoryStream zipstream = new System.IO.MemoryStream();
62 using (var fs = new FileStream(fileInfo.FullName, FileMode.Open))
63 {
64 fs.CopyTo(zipstream);
65 fs.Close();
66 fs.Dispose();
67 }
68 if (System.IO.File.Exists(fsUrl))
69 {
70 System.IO.File.Delete(fsUrl);
71 }
72 return File(zipstream.ToArray(), "application/x-zip-compressed", "营收月报.zip");
73 }
74 }
View Code
调用的生成压缩包文件帮助类对应方法也分享出来:
using ICSharpCode.SharpZipLib.Zip;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace myProject
{
public static class ZipHelper
{
static ZipHelper()
{
//消除文件名中文乱码
ICSharpCode.SharpZipLib.Zip.ZipStrings.CodePage = Encoding.UTF8.CodePage;
//旧版本
//ICSharpCode.SharpZipLib.Zip.ZipConstants.DefaultCodePage = Encoding.UTF8.CodePage;
}
#region 压缩文件
/// <summary>
/// 压缩文件
/// </summary>
/// <param name="dest">目的文件,如: c:\test.zip</param>
/// <param name="fileAbsPaths">文件来源列表,如: c:\test.txt,d:\test.db</param>
public static void ZipFile(string dest, List<string> fileAbsPaths)
{
using (var fs = new FileStream(dest, FileMode.Create))
{
var zipOutputStream = new ZipOutputStream(fs);
foreach (var i in fileAbsPaths)
{
ZipSingleFile(zipOutputStream, i);
//删除源文件
File.Delete(i);
};
zipOutputStream.Finish();
zipOutputStream.Close();
}
}
private static void ZipSingleFile(ZipOutputStream zipOutputStream, string filePath, string folderName = "")
{
var fileInfo = new FileInfo(filePath);
string fileName = Path.Combine(folderName, fileInfo.Name);
ZipEntry zipEntry = new ZipEntry(Encoding.UTF8.GetString(Encoding.UTF8.GetBytes(fileName)));
zipEntry.DateTime = DateTime.Now;
zipEntry.Size = fileInfo.Length;
zipOutputStream.PutNextEntry(zipEntry);
using (var fs = new FileStream(fileInfo.FullName, FileMode.Open))
{
fs.CopyTo(zipOutputStream);
fs.Close();
}
}
private static void ZipSingleFolder(ZipOutputStream zipOutputStream, string folderPath, string folderName = "")
{
string[] directorys = Directory.GetDirectories(folderPath);
foreach (var i in directorys)
{
var tmp = Path.Combine(folderName, new DirectoryInfo(i).Name);
ZipSingleFolder(zipOutputStream, i, tmp);
}
string[] files = Directory.GetFiles(folderPath);
foreach (var i in files)
{
ZipSingleFile(zipOutputStream, i, folderName);
}
}
/// <summary>
/// 递归压缩文件夹
/// </summary>
/// <param name="dest">目的文件名称,如: c:\test.zip</param>
/// <param name="folderPaths">压缩的目录列表,如: c:\test,d:\jack</param>
public static void ZipFolder(string dest, params string[] folderPaths)
{
using (var fs = new FileStream(dest, FileMode.Create))
{
var zipOutputStream = new ZipOutputStream(fs);
foreach (var i in folderPaths)
{
ZipSingleFolder(zipOutputStream, i, new DirectoryInfo(i).Name);
};
zipOutputStream.Finish();
zipOutputStream.Close();
}
}
/// <summary>
/// 递归压缩文件夹里的内容,不包含文件夹本身(区别:ZipFolder() )
/// </summary>
/// <param name="dest">目的文件名称,如: c:\test.zip</param>
/// <param name="folderPath">压缩的目录列表,如: c:\test</param>
public static void ZipFolderContent(string dest, string folderPath)
{
using (var fs = new FileStream(dest, FileMode.Create))
{
var zipOutputStream = new ZipOutputStream(fs);
string[] directorys = Directory.GetDirectories(folderPath);
foreach (var i in directorys)
{
var tmp = Path.Combine(new DirectoryInfo(i).Name);
ZipSingleFolder(zipOutputStream, i, tmp);
}
string[] files = Directory.GetFiles(folderPath);
foreach (var i in files)
{
ZipSingleFile(zipOutputStream, i);
}
zipOutputStream.Finish();
zipOutputStream.Close();
}
}
#endregion
#region 解压缩文件
/// <summary>
/// 解压缩文件到指定文件夹
/// </summary>
/// <param name="srcZipFile">源压缩文件</param>
/// <param name="destDir">目标文件夹</param>
/// <returns></returns>
public static void UnZipFile(string srcZipFile, string destDir)
{
if (!Directory.Exists(destDir)) Directory.CreateDirectory(destDir);
using (var stream = new ZipInputStream(File.OpenRead(srcZipFile.Trim())))
{
ZipEntry entry;
while ((entry = stream.GetNextEntry()) != null)
{
if (entry.IsDirectory)
{
//目录,创建新目录即可
var path = Path.Combine(destDir, entry.Name);
if (!Directory.Exists(path)) Directory.CreateDirectory(path);
continue;
}
else if (entry.IsFile)
{
//文件,将文件解压缩
var path = Path.Combine(destDir, entry.Name);
var dir = Path.GetDirectoryName(path);
if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
using (var fs = File.Create(path))
{
int size = 2048;
byte[] data = new byte[2048];
while (true)
{
size = stream.Read(data, 0, data.Length);
if (size > 0)
{
fs.Write(data, 0, size);
}
else
{
break;
}
}
}
}
}
}
}
#endregion
}
}
View Code
基本实现原理就是这样,如果大家有更好的方式欢迎下方留言交流~
生命不息,奋斗不止!只要相信,只要坚持,只要你真的是用生命在热爱,那一定是天赋使命使然,那就是一个人该坚持和努力的东西,无论梦想是什么,无论路有多曲折多遥远,只要是灵魂深处的热爱,就会一直坚持到走上属于自己的舞台!