npoi 實現類似excel、word自身的加密解密效果


 

                 最近在做一個文件管理系統,要求上傳的excel、word、pdf 文件加密存在服務器上。在系統里下載可以不輸密碼直接打開,在服務器上點開文件必須要輸密碼。要考慮做好一勞永逸、也不能用收費的。以前沒做過關於文檔加密的東西,網上搜了好多, 可以實現加密解密的大致分為3種:

1:Spire

參考地址:https://zhidao.baidu.com/question/560428556.html

有免費的,我下載dll做完后發現有水印,因為公司的文件都是很正式的文件,所以果斷放棄了它。這款能實現多種類型的文件加密解密,如果公司願意花錢買,用這個還是很不錯的。可以給我們開發人員省很多事。

使用步驟:免費版本可以在官網下載,然后把dll文件引入項目就可以使用了( Free Spire.Xls)。
以下幾個網址介紹的很詳細,
                   https://www.cnblogs.com/asxinyu/p/4346907.html
                  https://www.cnblogs.com/cjm123/p/8660810.html
上代碼:

  

  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 版本不一樣導致。

介紹如何引用: https://blog.csdn.net/weixin_39029925/article/details/75389075
參考的文章:https://www.cnblogs.com/teamblog/p/6158140.html

上代碼: mvc、uploadify文件插件。(以下代碼只能保證實現 xlsx、docx 格式的加密解密)

 

  1   //此部分是加密的方法。
  2    #region 表格上傳下載頁的文件上傳
  3    
  4    int SetFileSize = Convert.ToInt32(ConfigurationManager.AppSettings["SetFileSize"]);
  5    
  6    /// <summary>
  7      /// 文件上傳 
  8      /// </summary>
  9     /// <returns></returns>
 10    public JsonResult UpLoadFile()
 11    {
 12        HttpFileCollectionBase file = Request.Files;
 13        string url = "";
 14    
 15        string fileName = "";//最終的文件名
 16        string Name = "";
 17        string FilePsd = "";//文件加密的密碼
 18        string DepName = HttpUtility.UrlDecode(Request.QueryString["DepName"].Trim());
 19        string ProjectName = HttpUtility.UrlDecode(Request.QueryString["ProjectName"].Trim());
 20        string Updatetime = Request.QueryString["Updatetime"];
 21        string FormId = Request.QueryString["FormId"];
 22    
 23        if (Updatetime.Contains("中國標准時間"))
 24        {
 25            Updatetime = Updatetime.Trim().Replace("GMT 0800 (中國標准時間)", "");
 26        }
 27        else
 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)
 34       string FileName = HttpUtility.UrlDecode(Request.QueryString["FileName"].Trim());
 35   
 36       string fileType = "";
 37       TimeSpan span = DateTime.Now - Convert.ToDateTime(Updatetime);
 38       if (span.TotalHours > 24)
 39       {
 40           return Json(new { url = "", name = "-2" });//該文件在24小時內沒有修改過不能上傳
 41       }
 42       if (file.Count > 0)
 43       {
 44           if (file[0].ContentLength != 0)
 45           {
 46               Name = FileName;
 47               fileType = Name.ToString().Substring(Name.LastIndexOf("."));
 48               int length = Name.Length - fileType.Length;
 49               Name = Name.ToString().Substring(0, length);
 50               if (Name.Contains('.'))
 51               {
 52                   fileName = Name.ToString().Substring(0, length).Remove('.') + Encryption.GenerateRandomNumber(10);//表格名稱+隨機數;
 53               }
 54               else
 55               {
 56                   fileName = Name + Encryption.GenerateRandomNumber(10);//表格名稱+隨機數;
 57               }
 58               if (fileType != "*.xls" || fileType != "*.xlsx" || fileType != "*.pdf")
 59               {
 60                   //DailyForm/項目名稱/部門名稱/年/月/文件
 61                   string filePath = ConfigurationManager.AppSettings["DailyForm"] + "/" + ProjectName + "/" + DepName
 62                   + "/" + ComFunction.GetYear(DateTime.Now.ToString())
 63                     + "/" + ComFunction.GetMonth(DateTime.Now.ToString())
 64                    + "/" + fileName + fileType;
 65                   url = filePath;
 66                   if (!Directory.Exists(Server.MapPath(filePath)))
 67                   {
 68                       Directory.CreateDirectory(Server.MapPath(filePath).Substring(0, Server.MapPath(filePath).LastIndexOf('\\')));
 69                   }
 70                   try
 71                   {
 72                       string savePath = Server.MapPath(filePath);
 73                       //把傳入的原始文件存到文件夾。
 74                       file[0].SaveAs(savePath);
 75   
 76                       //判斷該表格是否是敏感數據
 77                       string result = SQLHelper.GetFieldValue2("File", "t_able", "  and Id=@Id", new List<KeyValue> { new KeyValue { Key = "@Id", Value = FormId } });//是否是敏感的 0  不是  1 是
 78    
 79                           if (result != "1")
 80                           {
 81                               FilePsd = "0";
 82                           }
 83                           else  //需要加密文件
 84                           {
 85                               FilePsd = Encryption.GenerateRandomNumber(6);
 86    
 87                              
 88                            //====================================這里是加密主要的代碼==================================
 89    
 90                               //如果類型是.docx  、 xlsx,直接加密  Nipo
 91                               if (fileType == ".docx" || fileType == ".xlsx")
 92                               {
 93                                   using (OfficeCryptoStream stream = OfficeCryptoStream.Open(@"" + savePath))
 94                                   {
 95                                       stream.Password = FilePsd;
 96                                       bool a = stream.Encrypted;
 97                                       stream.Save();
 98                                   }
 99                               }
100                        //轉換格式還未實現,搜了一些辦法,都不適用。等以后做出來了來更新。
101                               else  //如果是  *.xls; *.pdf;*.doc; *.rtf;先轉換成 docx、xlsx、
102                               {
103                                   if (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");
126    
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    
159                            if (new FileInfo(Server.MapPath(filePath)).Length <= SetFileSize)//
160                            {
161                            }
162                            else
163                            {
164                                //大於XM
165                                System.IO.File.Delete(Server.MapPath(filePath));
166                            }
167    
168                        }
169                        catch (Exception ex)
170                        {
171                        }
172                        Name = Name + fileType;
173                    }
174                    else
175                    {
176                        return Json(new { url = "", name = "-1" });//格式不合法
177                    }
178                }
179            }
180            url = System.Web.HttpUtility.UrlEncode(url);
181            Name = System.Web.HttpUtility.UrlEncode(Name + "&" + FilePsd);
182            return 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>
  9         public 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();
 16             try
 17             {
 18                 string DownFormName = "";
 19                 string FileCompletePath = "";//原文件完整路徑
 20                 string CopyFileCompletePath = "";//復制文件完整路徑
 21                 string FilePsd = "";//文件密碼
 22                 string NewPath = "";//生成臨時新的文件。
 23                 bool ExistFile = false;
 24                 //下載輸出 
 25                 if (type == 1)
 26                 {
 27                     DownFormName = "表格模板___" + FormName; 
 28                 }
 29                 else
 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  不是  其他 是
 35                     if (FilePsd != "0" && FilePsd != "" && (FilePath.Contains(".pdf")!=true))//需要解密文件
 36                     {
 37                         ExistFile = ComFunction.ExistFilePath(FilePath);
 38                         if (ExistFile )  //如果文件存在並且文件不是pdf
 39                         { 
 40                             string[] arrry = FilePath.Split('/');
 41                             for (int i = 0; i < arrry.Length; i++)
 42                             {
 43                                 if (i > 1 && i != 7)
 44                                 {
 45                                     NewPath = NewPath + '/' + arrry[i];
 46                                 }
 47                             }
 48                             NewPath = ("~/DeclassifiedFile" + NewPath + '/' + Encryption.GenerateRandomNumber(4) + arrry[7]).Trim();
 49 
 50                             //路徑不存在創建路徑
 51                             if (!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                             ////解密
 67                             using (OfficeCryptoStream stream = OfficeCryptoStream.Open(@"" + CopyFileCompletePath, FilePsd))
 68                             {
 69                                 stream.Password = null;
 70                                 bool b = stream.Encrypted;
 71                                 stream.Save();
 72                                 FilePath = NewPath;
 73                             }
 74                         }
 75                     }
 76                     else
 77                     {
 78 
 79                     }
 80                 }
 81                   //執行下載方法
 82                 string result = ComFunction.DownLoadFile(DownFormName, FilePath);
 83                 string remark = "";
 84                 if (FilePsd != "0")//需要解密文件
 85                 {
 86                     //刪除零時被解密的文件
 87                     if (CopyFileCompletePath.Length > 1)
 88                     {
 89 
 90                         bool IsDelete = DeleteFile(CopyFileCompletePath);
 91 
 92                         if (!IsDelete)
 93                         {
 94                             string filePath = "~/Log/";
 95 
 96                             if (!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 
105                 if (!result.Contains("-1"))
106                 {
107 
108                     if (type2 == 0)
109                     {
110                         remark = "在上傳下載頁面";
111                     }
112                     else if (type2 == 1)
113                     {
114                         remark = "在審批頁面";
115                     }
116                     else if (type2 == 3)
117                     {
118                         remark = "在審批記錄頁面";
119 
120                     }
121                     else if (type2 == 4)
122                     {
123                         remark = "在日常表格列表查詢頁面";
124 
125                     }
126                     else if (type2 == 5)
127                     {
128                         remark = "在打印頁面";
129 
130                     }
131                     else if (type2 == 6)
132                     {
133                         remark = "在打印模板詳情頁_表格";
134 
135                     }
136 
137                     else if (type2 == 7)
138                     {
139                         remark = "在打印模板詳情頁_附件";
140 
141                     }
142 
143 
144 
145                     remark = remark + (type == 0 ? "下載了提交的日常表格:" : "下載了表格模板:");
146                     string optName = "下載";
147                     if (type2 == 7 || type2 == 6)
148                     {
149                         optName = "打印__下載";
150                     }
151                     // 添加數據到上傳下載表、表格操作記錄表 
152                     int count = BLL_FormOperationRecord.AddFormOperationRecord(UploadDownloadId, UserInfo.Id, DownTime, optName, remark + FormName); 
153 
154                     if (count > 0)
155                     {
156 
157                     }
158                     else
159                     {
160 
161                         //添加失敗
162                         
163                     }
164 
165                 }
166                 else
167                 { 
168                 }
169             }
170 
171 
172 
173             catch (Exception ex)
174             {
175 
176                 //寫入錯誤日志
177                 LogHelper.WriteExceptionLogToText(ex);
178             }
179 
180         }

 

                第一次寫文章,由於不熟悉這個編輯器,重來了好多遍。 條理可能不太清晰,以后寫多了應該邏輯思維就會好點。感謝提供參考文章的大佬們。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM