npoi实现类似excel、word⾃⾝的加密解密效果
最近在做⼀个⽂件管理系统,要求上传的excel、word、pdf ⽂件加密存在服务器上。在系统⾥下载可以不输密码直接打开,在服务器上点开⽂件必须要输密码。要考虑做好⼀劳永逸、也不能⽤收费的。以前没做过关于⽂档加密的东西,⽹上搜了好多,可以实现加密解密的⼤致分为3种:
1:Spire
有免费的,我下载dll做完后发现有⽔印,因为公司的⽂件都是很正式的⽂件,所以果断放弃了它。这款能实现多种类型的⽂件加密解密,如果公司愿意花钱买,⽤这个还是很不错的。可以给我们开发⼈员省很多事。
using添加引⽤。
//加密
//初始化⼀个⼯作簿并加载⼀个⼯作簿实例
Workbook book = new Workbook();
book.LoadFromFile("d://test.xls");
//为⼯作簿设置访问密码
book.Protect("123");
//保存并打开⽂档
book.SaveToFile("d://test.xls", ExcelVersion.Version2013);
//解密
//初始化⼀个Workbook实例
Workbook workbook = new Workbook();
//输⼊密码并加载⽂档
workbook.OpenPassword = ("123");
workbook.LoadFromFile("d://test.xls", ExcelVersion.Version2013);
//取消保护
workbook.UnProtect();
//保存
workbook.SaveToFile("d://test.xls", ExcelVersion.Version2013)
//word加密
// savePath绝对路径
//doc 可以,但是眉头加了⼀⾏⽔印。docx没有被加密
//Document document = new Document();
//document.LoadFromFile(@"" + savePath);
//document.Encrypt("000");
//document.SaveToFile(savePath);
2:C# Office组件 dll word.dll excel.dll
没⽤这个原因是:
要保证机器本⾝安装了office.因为客户分布⽐较⼴,不能保证每个⽤户电脑都安装了这个组件。所以没有⽤代码试。
3:NPOI
这个是免费的,但是我搜到的可以加密的格式并不多,但是由于系统中pdf ⽂件极少出现,我只需要操作xlsx、docx 格式的⽂件就好,所以还是可以满⾜我的需求,就⽤了这个。在做的过程中只到了如何⽤npio 加密,没有看到解密的。只加密不能解密也不⾏啊,后来搜了好多还是没到解决办法,灵机⼀动,把加密的参数赋为null,下载下来的⽂件就直接打开了。终于在答应交东西⽇期之前把功能实现了。然后就想着记录⼀下给别⼈参考,别⼈在着急⽤的时候业务相同可以直接拿去⽤了。⾃⼰做了这⼏年的开发,每次都是搜别⼈的东西⽤,今天开始也记录些东西给别⼈提供⽅便。
看到有的⽂章说xls也可以实现,但是我在试的过程中,并没有成功,不知道是不是dll 版本不⼀样导致。
上代码: mvc、uploadify⽂件插件。(以下代码只能保证实现 xlsx、docx 格式的加密解密)
1//此部分是加密的⽅法。
2#region表格上传下载页的⽂件上传
3
4int SetFileSize = Convert.ToInt32(ConfigurationManager.AppSettings["SetFileSize"]);
5
6///<summary>
7///⽂件上传
8///</summary>
9///<returns></returns>
10public JsonResult UpLoadFile()
11 {
12 HttpFileCollectionBase file = Request.Files;
13string url = "";
14
15string fileName = "";//最终的⽂件名
16string Name = "";
17string FilePsd = "";//⽂件加密的密码
18string DepName = HttpUtility.UrlDecode(Request.QueryString["DepName"].Trim());
19string ProjectName = HttpUtility.UrlDecode(Request.QueryString["ProjectName"].Trim());
20string Updatetime = Request.QueryString["Updatetime"];
21string FormId = Request.QueryString["FormId"];
23if (Updatetime.Contains("中国标准时间"))
24 {
25 Updatetime = Updatetime.Trim().Replace("GMT 0800 (中国标准时间)", "");
26 }
27else
28 {
29 Updatetime = Updatetime.Trim().Replace("GMT 0800 (China Standard Time)", "");
30
31 }
32//中⽂:Wed Aug 07 2019 16:27:32 GMT+0800 (中国标准时间)
33//英⽂:Mon Sep 02 2019 09:11:01 GMT 0800 (China Standard Time)
34string FileName = HttpUtility.UrlDecode(Request.QueryString["FileName"].Trim());
35
36string fileType = "";
37 TimeSpan span = DateTime.Now - Convert.ToDateTime(Updatetime);
38if (span.TotalHours > 24)
39 {
40return Json(new { url = "", name = "-2" });//该⽂件在24⼩时内没有修改过不能上传
41 }
42if (file.Count > 0)
43 {
44if (file[0].ContentLength != 0)
45 {
46 Name = FileName;
47 fileType = Name.ToString().Substring(Name.LastIndexOf("."));
48int length = Name.Length - fileType.Length;
49 Name = Name.ToString().Substring(0, length);
50if (Name.Contains('.'))
51 {
52 fileName = Name.ToString().Substring(0, length).Remove('.') + Encryption.GenerateRandomNumber(10);//表格名称+随机数;
53 }
54else
55 {
56 fileName = Name + Encryption.GenerateRandomNumber(10);//表格名称+随机数;
57 }
58if (fileType != "*.xls" || fileType != "*.xlsx" || fileType != "*.pdf")
59 {
60//DailyForm/项⽬名称/部门名称/年/⽉/⽂件
61string filePath = ConfigurationManager.AppSettings["DailyForm"] + "/" + ProjectName + "/" + DepName
62 + "/" + ComFunction.GetYear(DateTime.Now.ToString())
63 + "/" + ComFunction.GetMonth(DateTime.Now.ToString())
64 + "/" + fileName + fileType;
65 url = filePath;
66if (!Directory.Exists(Server.MapPath(filePath)))
67 {
68 Directory.CreateDirectory(Server.MapPath(filePath).Substring(0, Server.MapPath(filePath).LastIndexOf('\\')));
69 }
70try
71 {
72string savePath = Server.MapPath(filePath);
73//把传⼊的原始⽂件存到⽂件夹。
74 file[0].SaveAs(savePath);
75
76//判断该表格是否是敏感数据
77string result = SQLHelper.GetFieldValue2("File", "t_able", " and Id=@Id", new List<KeyValue> { new KeyValue { Key = "@Id", Value = FormId } });//是否是敏感的 0 不是 1 是 78
79if (result != "1")
80 {
81 FilePsd = "0";
82 }
83else//需要加密⽂件
84 {
85 FilePsd = Encryption.GenerateRandomNumber(6);
86
87
88//====================================这⾥是加密主要的代码==================================
89
90//如果类型是.docx 、 xlsx,直接加密 Nipo
91if (fileType == ".docx" || fileType == ".xlsx")
92 {
93using (OfficeCryptoStream stream = OfficeCryptoStream.Open(@"" + savePath))
94 {
95 stream.Password = FilePsd;
96bool a = stream.Encrypted;
97 stream.Save();
98 }
99 }
100//转换格式还未实现,搜了⼀些办法,都不适⽤。等以后做出来了来更新。
101else//如果是 *.xls; *.pdf;*.doc; *.rtf;先转换成 docx、xlsx、
102 {
103if (fileType == ".pdf")
104 {
105//Workbook workbook1 = new Workbook();
106//workbook1.SaveCopyAs(savePath);
107//workbook1.Password = "123";
108//workbook1.SaveAs();
109//workbook1.Unprotect("123");
110
111 }
112 }
113
114
115 }
116
117
118
119
120//初始化⼀个⼯作簿并加载⼀个⼯作簿实例
121//Workbook book = new Workbook();
122//book.LoadFromFile(savePath);//"test.xls"
123
124////为⼯作簿设置访问密码
125//book.Protect("147");
127////保存并打开⽂档
128//book.SaveToFile(savePath, ExcelVersion.Version2013);
129
130
131// Workbook workbook = new Workbook();
132//workbook.LoadFromFile(@"" + savePath);
133//workbook.SaveToFile(savePath.Substring(0, savePath.Length-3)+ "xlsx", ExcelVersion.Version97to2003);//⽬标⽂件.xlsx
134
135
136
137
138
139
140//正确
141//doc、可以,但是眉头加了⼀⾏标志 docx没有被加密
142//Document document = new Document();
143//document.LoadFromFile(@"" + savePath);
144//document.Encrypt("000");
145//document.SaveToFile(savePath);
146
147
148
149
150//初始化⼀个Document类实例并加载需要加密的Word⽂档
151//Document doc = new Document(@"C:\Users\Administrator\Desktop\sample.docx");
152// Document doc = new Document(Server.MapPath(filePath));
153//Document doc = new Document(@"D:\32324.docx");
154////设置打开Word⽂档的密码
155//doc.Encrypt("123");
156////保存并打开⽂档
157//doc.SaveToFile( "sds.docx", FileFormat.Docx);
158
159if (new FileInfo(Server.MapPath(filePath)).Length <= SetFileSize)//
160 {
161 }
162else
163 {
164//⼤于XM
165 System.IO.File.Delete(Server.MapPath(filePath));
166 }
167
168 }
169catch (Exception ex)
170 {
171 }
172 Name = Name + fileType;
173 }
174else
175 {
176return Json(new { url = "", name = "-1" });//格式不合法
177 }
178 }
179 }
180 url = System.Web.HttpUtility.UrlEncode(url);
181 Name = System.Web.HttpUtility.UrlEncode(Name + "&" + FilePsd);
182return Json(new { url = url, name = Name });
183 }
184#endregion
此部分是解密的⽅法,⼤致思路是:获取到要下载的⽂件路径,复制⽂件(a)到另⼀个⽂件夹(b),把b的⽂件解密保存,去下载b 的⽂件。因为有服务在监控a⽂件夹的⽂件,会把他复制到另⼀个服务器。后台⽤代码把⽂件复制⼀份再解密后下载解密的⽂件。这样能保证原始⽂件密码始终存在,服务监控复制⽂件不会把解密的⽂件⼀起复制⾛了。
1///<summary>
2///原⽂件下载和操作员上传的⽂件下载⽅法
3///</summary>
4///<param name="UploadDownloadId">上传下载ID</param>
5///<param name="FilePath"></param>
6///<param name="FormName"></param>
7///<param name="type">0:下载提交的⽇常表格,1下载表格模板</param>
8///<param name="type2">0:上传下载页⾯,1审批页⾯</param>
9public void DownFile(string FilePath, string FormName, int UploadDownloadId, int type, int type2)
10 {
11//判断是否有下载权限
12 EnUser UserInfo = Session["UserInfo"] as EnUser;
13
14 DateTime DownTime = DateTime.Now;
15 EnUploadDownload UploadDownload = new EnUploadDownload();
16try
17 {
18string DownFormName = "";
19string FileCompletePath = "";//原⽂件完整路径
20string CopyFileCompletePath = "";//复制⽂件完整路径
21string FilePsd = "";//⽂件密码
22string NewPath = "";//⽣成临时新的⽂件。
23bool ExistFile = false;
24//下载输出
25if (type == 1)
26 {getsavefilename
27 DownFormName = "表格模板___" + FormName;
28 }
29else
30 {
31 DownFormName = FormName;
32//先把⽂件解密存在新的⽂件夹下载完毕然后删掉
33//根据UploadDownloadId 查需不需要解密,0不需要,其他需要。
34 FilePsd = SQLHelper.GetFieldValue2("FilePwd", "t_table", " and Id=@Id", new List<KeyValue> { new KeyValue { Key = "@Id", Value = UploadDownloadId } });//是否需要解密的 0 不是其他是 35if (FilePsd != "0" && FilePsd != "" && (FilePath.Contains(".pdf")!=true))//需要解密⽂件
36 {
37 ExistFile = ComFunction.ExistFilePath(FilePath);
38if (ExistFile ) //如果⽂件存在并且⽂件不是pdf
41for (int i = 0; i < arrry.Length; i++)
42 {
43if (i > 1 && i != 7)
44 {
45 NewPath = NewPath + '/' + arrry[i];
46 }
47 }
48 NewPath = ("~/DeclassifiedFile" + NewPath + '/' + Encryption.GenerateRandomNumber(4) + arrry[7]).Trim();
49
50//路径不存在创建路径
51if (!Directory.Exists(Server.MapPath(NewPath)))
52 {
53 Directory.CreateDirectory(Server.MapPath(NewPath).Substring(0, Server.MapPath(NewPath).LastIndexOf('\\')));
54 }
55//获取完整路径
56 FileCompletePath = ComFunction.CompletePath(FilePath);
57 CopyFileCompletePath = ComFunction.CompletePath(NewPath);
58
59//====================================这⾥是解密主要的代码==================================
60
61//复制加密的⽂件到其他地址
62 FileInfo fi1 = new FileInfo(FileCompletePath);
63 FileInfo fi2 = new FileInfo(CopyFileCompletePath);
64 fi1.CopyTo(CopyFileCompletePath);
65
66////解密
67using (OfficeCryptoStream stream = OfficeCryptoStream.Open(@"" + CopyFileCompletePath, FilePsd))
68 {
69 stream.Password = null;
70bool b = stream.Encrypted;
71 stream.Save();
72 FilePath = NewPath;
73 }
74 }
75 }
76else
77 {
78
79 }
80 }
81//执⾏下载⽅法
82string result = ComFunction.DownLoadFile(DownFormName, FilePath);
83string remark = "";
84if (FilePsd != "0")//需要解密⽂件
85 {
86//删除零时被解密的⽂件
87if (CopyFileCompletePath.Length > 1)
88 {
89
90bool IsDelete = DeleteFile(CopyFileCompletePath);
91
92if (!IsDelete)
93 {
94string filePath = "~/Log/";
95
96if (!Directory.Exists(Server.MapPath(filePath)))
97 {
98 Directory.CreateDirectory(Server.MapPath(NewPath).Substring(0, Server.MapPath(filePath).LastIndexOf('\\')));
99 }
100 LogHelper.OtherErroLogText2("下载⽂件时,备份⽂件没有被删除,⽂件路径:" + CopyFileCompletePath, ComFunction.CompletePath(filePath)); 101 }
102 }
103 }
104
105if (!result.Contains("-1"))
106 {
107
108if (type2 == 0)
109 {
110 remark = "在上传下载页⾯";
111 }
112else if (type2 == 1)
113 {
114 remark = "在审批页⾯";
115 }
116else if (type2 == 3)
117 {
118 remark = "在审批记录页⾯";
119
120 }
121else if (type2 == 4)
122 {
123 remark = "在⽇常表格列表查询页⾯";
124
125 }
126else if (type2 == 5)
127 {
128 remark = "在打印页⾯";
129
130 }
131else if (type2 == 6)
132 {
133 remark = "在打印模板详情页_表格";
134
135 }
136
137else if (type2 == 7)
138 {
139 remark = "在打印模板详情页_附件";
140
141 }
142
143
145 remark = remark + (type == 0 ? "下载了提交的⽇常表格:" : "下载了表格模板:");
146string optName = "下载";
147if (type2 == 7 || type2 == 6)
148 {
149 optName = "打印__下载";
150 }
151// 添加数据到上传下载表、表格操作记录表
152int count = BLL_FormOperationRecord.AddFormOperationRecord(UploadDownloadId, UserInfo.Id, DownTime, optName, remark + FormName);
153
154if (count > 0)
155 {
156
157 }
158else
159 {
160
161//添加失败
162
163 }
164
165 }
166else
167 {
168 }
169 }
170
171
172
173catch (Exception ex)
174 {
175
176//写⼊错误⽇志
177 LogHelper.WriteExceptionLogToText(ex);
178 }
179
180 }
第⼀次写⽂章,由于不熟悉这个编辑器,重来了好多遍。条理可能不太清晰,以后写多了应该逻辑思维就会好点。感谢提供参考⽂章的⼤佬们。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论