最近在做一个文件管理系统,要求上传的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(""); //保存并打开文档
book.SaveToFile("d://test.xls", ExcelVersion.Version2013); //解密
//初始化一个Workbook实例
Workbook workbook = new Workbook(); //输入密码并加载文档
workbook.OpenPassword = ("");
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 格式的加密解密)

   //此部分是加密的方法。
#region 表格上传下载页的文件上传 int SetFileSize = Convert.ToInt32(ConfigurationManager.AppSettings["SetFileSize"]); /// <summary>
/// 文件上传
/// </summary>
/// <returns></returns>
public JsonResult UpLoadFile()
{
HttpFileCollectionBase file = Request.Files;
string url = ""; string fileName = "";//最终的文件名
string Name = "";
string FilePsd = "";//文件加密的密码
string DepName = HttpUtility.UrlDecode(Request.QueryString["DepName"].Trim());
string ProjectName = HttpUtility.UrlDecode(Request.QueryString["ProjectName"].Trim());
string Updatetime = Request.QueryString["Updatetime"];
string FormId = Request.QueryString["FormId"]; if (Updatetime.Contains("中国标准时间"))
{
Updatetime = Updatetime.Trim().Replace("GMT 0800 (中国标准时间)", "");
}
else
{
Updatetime = Updatetime.Trim().Replace("GMT 0800 (China Standard Time)", ""); }
//中文:Wed Aug 07 2019 16:27:32 GMT+0800 (中国标准时间)
//英文:Mon Sep 02 2019 09:11:01 GMT 0800 (China Standard Time)
string FileName = HttpUtility.UrlDecode(Request.QueryString["FileName"].Trim()); string fileType = "";
TimeSpan span = DateTime.Now - Convert.ToDateTime(Updatetime);
if (span.TotalHours > )
{
return Json(new { url = "", name = "-2" });//该文件在24小时内没有修改过不能上传
}
if (file.Count > )
{
if (file[].ContentLength != )
{
Name = FileName;
fileType = Name.ToString().Substring(Name.LastIndexOf("."));
int length = Name.Length - fileType.Length;
Name = Name.ToString().Substring(, length);
if (Name.Contains('.'))
{
fileName = Name.ToString().Substring(, length).Remove('.') + Encryption.GenerateRandomNumber();//表格名称+随机数;
}
else
{
fileName = Name + Encryption.GenerateRandomNumber();//表格名称+随机数;
}
if (fileType != "*.xls" || fileType != "*.xlsx" || fileType != "*.pdf")
{
//DailyForm/项目名称/部门名称/年/月/文件
string filePath = ConfigurationManager.AppSettings["DailyForm"] + "/" + ProjectName + "/" + DepName
+ "/" + ComFunction.GetYear(DateTime.Now.ToString())
+ "/" + ComFunction.GetMonth(DateTime.Now.ToString())
+ "/" + fileName + fileType;
url = filePath;
if (!Directory.Exists(Server.MapPath(filePath)))
{
Directory.CreateDirectory(Server.MapPath(filePath).Substring(, Server.MapPath(filePath).LastIndexOf('\\')));
}
try
{
string savePath = Server.MapPath(filePath);
//把传入的原始文件存到文件夹。
file[].SaveAs(savePath); //判断该表格是否是敏感数据
string result = SQLHelper.GetFieldValue2("File", "t_able", " and Id=@Id", new List<KeyValue> { new KeyValue { Key = "@Id", Value = FormId } });//是否是敏感的 0 不是 1 是 if (result != "")
{
FilePsd = "";
}
else //需要加密文件
{
FilePsd = Encryption.GenerateRandomNumber(); //====================================这里是加密主要的代码================================== //如果类型是.docx 、 xlsx,直接加密 Nipo
if (fileType == ".docx" || fileType == ".xlsx")
{
using (OfficeCryptoStream stream = OfficeCryptoStream.Open(@"" + savePath))
{
stream.Password = FilePsd;
bool a = stream.Encrypted;
stream.Save();
}
}
//转换格式还未实现,搜了一些办法,都不适用。等以后做出来了来更新。
else //如果是 *.xls; *.pdf;*.doc; *.rtf;先转换成 docx、xlsx、
{
if (fileType == ".pdf")
{
//Workbook workbook1 = new Workbook();
//workbook1.SaveCopyAs(savePath);
//workbook1.Password = "123";
//workbook1.SaveAs();
//workbook1.Unprotect("123"); }
} } //初始化一个工作簿并加载一个工作簿实例
//Workbook book = new Workbook();
//book.LoadFromFile(savePath);//"test.xls" ////为工作簿设置访问密码
//book.Protect("147"); ////保存并打开文档
//book.SaveToFile(savePath, ExcelVersion.Version2013); // Workbook workbook = new Workbook();
//workbook.LoadFromFile(@"" + savePath);
//workbook.SaveToFile(savePath.Substring(0, savePath.Length-3)+ "xlsx", ExcelVersion.Version97to2003);//目标文件.xlsx //正确
//doc、 可以,但是眉头 加了一行标志 docx没有被加密
//Document document = new Document();
//document.LoadFromFile(@"" + savePath);
//document.Encrypt("000");
//document.SaveToFile(savePath); //初始化一个Document类实例并加载需要加密的Word文档
//Document doc = new Document(@"C:\Users\Administrator\Desktop\sample.docx");
// Document doc = new Document(Server.MapPath(filePath));
//Document doc = new Document(@"D:\32324.docx");
////设置打开Word文档的密码
//doc.Encrypt("123");
////保存并打开文档
//doc.SaveToFile( "sds.docx", FileFormat.Docx); if (new FileInfo(Server.MapPath(filePath)).Length <= SetFileSize)//
{
}
else
{
//大于XM
System.IO.File.Delete(Server.MapPath(filePath));
} }
catch (Exception ex)
{
}
Name = Name + fileType;
}
else
{
return Json(new { url = "", name = "-1" });//格式不合法
}
}
}
url = System.Web.HttpUtility.UrlEncode(url);
Name = System.Web.HttpUtility.UrlEncode(Name + "&" + FilePsd);
return Json(new { url = url, name = Name });
}
#endregion

此部分是解密的方法,大致思路是:获取到要下载的文件路径,复制文件(a)到另一个文件夹(b),把b的文件解密保存,去下载b 的文件。因为有服务在监控a文件夹 的文件,会把他复制到另一个服务器。后台用代码把文件复制一份再解密后下载解密的文件。 这样能保证原始文件密码始终存在,服务监控复制文件不会把解密的文件一起复制走了。

     /// <summary>
/// 原文件下载和操作员上传的文件下载方法
/// </summary>
/// <param name="UploadDownloadId">上传下载ID</param>
/// <param name="FilePath"></param>
/// <param name="FormName"></param>
/// <param name="type">0:下载提交的日常表格,1下载表格模板</param>
/// <param name="type2">0: 上传下载页面,1审批页面</param>
public void DownFile(string FilePath, string FormName, int UploadDownloadId, int type, int type2)
{
//判断是否有下载权限
EnUser UserInfo = Session["UserInfo"] as EnUser; DateTime DownTime = DateTime.Now;
EnUploadDownload UploadDownload = new EnUploadDownload();
try
{
string DownFormName = "";
string FileCompletePath = "";//原文件完整路径
string CopyFileCompletePath = "";//复制文件完整路径
string FilePsd = "";//文件密码
string NewPath = "";//生成临时新的文件。
bool ExistFile = false;
//下载输出
if (type == )
{
DownFormName = "表格模板___" + FormName;
}
else
{
DownFormName = FormName;
//先把文件解密存在新的文件夹下载完毕然后删掉
//根据UploadDownloadId 查找需不需要解密,0不需要,其他需要。
FilePsd = SQLHelper.GetFieldValue2("FilePwd", "t_table", " and Id=@Id", new List<KeyValue> { new KeyValue { Key = "@Id", Value = UploadDownloadId } });//是否需要解密的 0 不是 其他 是
if (FilePsd != "" && FilePsd != "" && (FilePath.Contains(".pdf")!=true))//需要解密文件
{
ExistFile = ComFunction.ExistFilePath(FilePath);
if (ExistFile ) //如果文件存在并且文件不是pdf
{
string[] arrry = FilePath.Split('/');
for (int i = ; i < arrry.Length; i++)
{
if (i > && i != )
{
NewPath = NewPath + '/' + arrry[i];
}
}
NewPath = ("~/DeclassifiedFile" + NewPath + '/' + Encryption.GenerateRandomNumber() + arrry[]).Trim(); //路径不存在创建路径
if (!Directory.Exists(Server.MapPath(NewPath)))
{
Directory.CreateDirectory(Server.MapPath(NewPath).Substring(, Server.MapPath(NewPath).LastIndexOf('\\')));
}
//获取完整路径
FileCompletePath = ComFunction.CompletePath(FilePath);
CopyFileCompletePath = ComFunction.CompletePath(NewPath); //====================================这里是解密主要的代码================================== //复制加密的文件到其他地址
FileInfo fi1 = new FileInfo(FileCompletePath);
FileInfo fi2 = new FileInfo(CopyFileCompletePath);
fi1.CopyTo(CopyFileCompletePath); ////解密
using (OfficeCryptoStream stream = OfficeCryptoStream.Open(@"" + CopyFileCompletePath, FilePsd))
{
stream.Password = null;
bool b = stream.Encrypted;
stream.Save();
FilePath = NewPath;
}
}
}
else
{ }
}
//执行下载方法
string result = ComFunction.DownLoadFile(DownFormName, FilePath);
string remark = "";
if (FilePsd != "")//需要解密文件
{
//删除零时被解密的文件
if (CopyFileCompletePath.Length > )
{ bool IsDelete = DeleteFile(CopyFileCompletePath); if (!IsDelete)
{
string filePath = "~/Log/"; if (!Directory.Exists(Server.MapPath(filePath)))
{
Directory.CreateDirectory(Server.MapPath(NewPath).Substring(, Server.MapPath(filePath).LastIndexOf('\\')));
}
LogHelper.OtherErroLogText2("下载文件时,备份文件没有被删除,文件路径:" + CopyFileCompletePath, ComFunction.CompletePath(filePath));
}
}
} if (!result.Contains("-1"))
{ if (type2 == )
{
remark = "在上传下载页面";
}
else if (type2 == )
{
remark = "在审批页面";
}
else if (type2 == )
{
remark = "在审批记录页面"; }
else if (type2 == )
{
remark = "在日常表格列表查询页面"; }
else if (type2 == )
{
remark = "在打印页面"; }
else if (type2 == )
{
remark = "在打印模板详情页_表格"; } else if (type2 == )
{
remark = "在打印模板详情页_附件"; } remark = remark + (type == ? "下载了提交的日常表格:" : "下载了表格模板:");
string optName = "下载";
if (type2 == || type2 == )
{
optName = "打印__下载";
}
// 添加数据到上传下载表、表格操作记录表
int count = BLL_FormOperationRecord.AddFormOperationRecord(UploadDownloadId, UserInfo.Id, DownTime, optName, remark + FormName); if (count > )
{ }
else
{ //添加失败 } }
else
{
}
} catch (Exception ex)
{ //写入错误日志
LogHelper.WriteExceptionLogToText(ex);
} }

第一次写文章,由于不熟悉这个编辑器,重来了好多遍。 条理可能不太清晰,以后写多了应该逻辑思维就会好点。感谢提供参考文章的大佬们。

npoi 实现类似excel、word自身的加密解密效果的更多相关文章

  1. AES加密、解密(linux、window加密解密效果一致,支持中文)

    转自: http://sunfish.iteye.com/blog/2169158 import java.io.UnsupportedEncodingException; import java.s ...

  2. NPOI - .NET Excel & Word操作组件

    概要 NPOI 是 POI 项目的 .NET 版本.POI是一个开源的Java读写Excel.WORD等微软OLE2组件文档的项目. NPOI是构建在POI 3.x版本之上的,它可以在没有安装Offi ...

  3. word&excel&ppt文档加密方式

    ppt excel word

  4. Npoi导入导出Excel操作

    之前公司的一个物流商系统需要实现对订单的批量导入和导出,翻阅了一些资料,最后考虑使用NPOI实现这个需求. 在winform上面实现excel操作:http://www.cnblogs.com/Cal ...

  5. C# 使用 NPOI 库读写 Excel 文件

    NPOI 是开源的 POI 项目的.NET版,可以用来读写Excel,Word,PPT文件.在处理Excel文件上,NPOI 可以同时兼容 xls 和 xlsx.官网提供了一份 Examples,给出 ...

  6. 如何在web中实现类似excel的表格控件

    Execl功能非常强大,内置的很多函数或公式可以大大提高对数据的加工处理能力.那么在web中有没有类似的控件呢?经过一番搜寻,发现handsontable具备了基本的excel功能支持公式,同时能对数 ...

  7. NPOI导入导出EXCEL通用类,供参考,可直接使用在WinForm项目中

    以下是NPOI导入导出EXCEL通用类,是在别人的代码上进行优化的,兼容xls与xlsx文件格式,供参考,可直接使用在WinForm项目中,由于XSSFWorkbook类型的Write方法限制,Wri ...

  8. .net利用NPOI导入导出Excel

    NPOI在.net中的操作Excel 1.读取 using (FileStream stream = new FileStream(@"c:\客户资料.xls", FileMode ...

  9. Aspose 强大的服务器端 excel word ppt pdf 处理工具

    Aspose 强大的服务器端 excel word ppt pdf 处理工具 http://www.aspose.com/java/word-component.aspx

随机推荐

  1. 算法习题---5.3字典(Uva10815)

    一:题目 给出一段英文,里面包含一些单词,空格和标点,单词不区分大小写,默认都为小写.按照字典序输出这些单词(这些单词不能有重复,字母全部变成小写) (一)样例输入 Adventures in Dis ...

  2. JS语言中的JSON.parse()和JSON.stringify()

    parse()用于从一个字符串中解析出json对象,如 var str = '{"name":"huangxiaojian","age":& ...

  3. jquery分页展示控件:kkpager

    kkpager v1.2 js分页展示控件,传入简单参数就能使用的分页效果控件 准备工作,引入js.css <script type="text/javascript" sr ...

  4. Terence’s Stuff: Why do we do research?

    This sound like a question best answered via a survey conducted by a body such as Vitae, an internat ...

  5. qt model--view-delegate模式的界面设计概念,ListView用法

    最经典的界面设计模式,必须知道. 作为 一种经典到 不能 再 经典 的 架构 模式, qt的model--view-delegate大 行其 道 有其 必然 的 道理. 通过 把 职责. 性质相近的 ...

  6. Linux 脚本语言入门

    0.脚本编写初步介绍 (1)脚本第一行以 #!/bin/sh 开始,也可以用 #!/bin/bash 开始,但是第一行必须以这种方式开始. (2)脚本名需要以.sh结尾 (3)#开头的句子表示注释 ( ...

  7. CentOS7.6安装Pycharm并添加快捷方式

    1.以用户身份登录jiangshan 并建立/home/jiangshan/pycharm文件夹2.下载 pycharm-community-anaconda-2019.1.3.tar.gz 放置在/ ...

  8. java当中请给出一个oracle的helloworld例子

    [学习笔记] 2.oracle的helloworld例子: import java.sql.*;public class OracleHello{    public static void main ...

  9. Struts笔记4

    Struts2-拦截器-单个拦截器 自定义拦截器 1.创建一个继承AbstractInterceptor的类 package com.gyf.web.interceptor; import com.o ...

  10. STL源码剖析——空间配置器Allocator#3 自由链表与内存池

    上节在学习第二级配置器时了解了第二级配置器通过内存池与自由链表来处理小区块内存的申请.但只是对其概念进行点到为止的认识,并未深入探究.这节就来学习一下自由链表的填充和内存池的内存分配机制. refil ...