最近在做一个文件管理系统,要求上传的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. 【Mybatis】MyBatis之配置自定义数据源(十一)

    本例是在[Mybatis]MyBatis之配置多数据源(十)的基础上进行拓展,查看本例请先学习第十章 实现原理 1.扩展Spring的AbstractRoutingDataSource抽象类(该类充当 ...

  2. Dockerfile-server1

    [root@lab2 docker-file]# cd server1/ [root@lab2 server1]# ls a.sh ddbes-server1-0.0.1-SNAPSHOT.jar D ...

  3. MySQL报错argument out of range 1055解决办法

    参考:https://www.cnblogs.com/liangbenstudy/p/10246895.html MySQL 5.7.22查询时候报错 argument out of range 报错 ...

  4. stm32f405xx.h头文件的问题Undefined symbol IS_TIM_BREAK_INSTANCE

    1. 在实际使用过程中发现,编译工程中,出了个错误Undefined symbol IS_TIM_BREAK_INSTANCE 经过查找,发现有两个stm32f405xx.h,其中一个是,安装的器件包 ...

  5. GitToc-为你的Github仓库的Readme自动生成一个目录

    维护自己的Github仓库的时候发现Github的Readme不支持Toc目录,所以就自己写了一个小工具. 工具地址:https://github.com/Holy-Shine/GitToc 简介 如 ...

  6. QT 读写.ini配置文件

    当需要存放的数据量较少时合适使用.ini配置文件. #include <QCoreApplication> #include <QSettings> void SystemSe ...

  7. 剑指offer31:整数中1出现的次数(从1到n整数中1出现的次数)

    1 题目描述 求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1.10.11.12.13因此共出现6次,但是对于后面问题他就没辙 ...

  8. 03 python 对象笔记

    类的命名方法 1.使用大驼峰命名法:每一个单词的首字母大写(第一个的也要)2.单词之间不需要下划线 对象的内置函数和属性 1.使用dir()函数来获取对象的内置方法和属性.返回值是一个列表.2.返回中 ...

  9. python检测当前端口是否使用

    基于python检测端口是否在使用 - 缘起花渊 - 博客园https://www.cnblogs.com/yqmcu/p/9804002.html def net_is_used(port,ip=' ...

  10. Singer House CodeForces - 830D (组合计数,dp)

    大意: 一个$k$层完全二叉树, 每个节点向它祖先连边, 就得到一个$k$房子, 求$k$房子的所有简单路径数. $DP$好题. 首先设$dp_{i,j}$表示$i$房子, 分出$j$条简单路径的方案 ...