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小时内删除。