嘿嘿,我来啦,最近忙啦几天,使用MVC把应该实现的一些功能实现了,说起来做项目,实属感觉蛮好的,即可以学习新的东西,又可以增加自己之前知道的知识的巩固,不得不说是双丰收啊,其实这周来就开始面对下载在挣扎啦,不知道从哪下手,而且自己针对一个文件下载的小小练习还是写过的,但是和项目中的下载完全就是两个世界,所以我只能抱着学习的心情查找资料啦,刚开始由于leader没有说怎么个下载的办法,我只能自己看些有关下载的资料啦,周一只是在猜测的学习,然后通过询问各路大神。就新学习了NOPI,当我看到Nopi下载表格数据的时间,我发现NOPI好优越啊,我之前还不知道的那,所以简单的学习一下的啦。
一.NPOI的简单学习
下面就简单的总结一个最简单的表格下载方法:
public static void GetDownLoaMonthExal(List<UserModel> model) { //表头 string[] exalHead = { "用户名", "密码"}; var workbook = new HSSFWorkbook(); //表格显示的名字 var sheet = workbook.CreateSheet("报表"); //记得在这里创建表头部对象,不能每次创建 //sheet.CreateRow(0).CreateCell(0).SetCellValue(exalHead[i]) var col = sheet.CreateRow(0); //遍历表头在exal表格中 for (int i = 0; i < exalHead.Length; i++) { //报表的头部 col.CreateCell(i).SetCellValue(exalHead[i]); } int a = 1; //遍历表数据 foreach (var item in model) { var row = sheet.CreateRow(a); row.CreateCell(0).SetCellValue(item.TAISYOU_GTD); row.CreateCell(1).SetCellValue(item.TEIKEI_CNT_1); a++; } var file = new FileStream(AppDomain.CurrentDomain.BaseDirectory + "1.xls", FileMode.Create); workbook.Write(file); file.Close(); }
上面就是简单的把网页上面的数据下载到Excel文件中,仅仅限制于简单的表格,并没有设置表格的样式以及颜色的;不过说起来使用NPOI,首先要下载NPOI,或者添加Nuget包即可,然后添加引用NPOI.HSSF.UserModel的引用,我们即可使用类HSSFWorkbook,然后创建对象,设计我们的表头和表数据。
好啦下面总结一下在MVC中实现和网站不同服务器的批量文件下载,其实周三Lender告诉我要实现这样的一个下载,我就不知打所措啦,在网上找了一些资料,感觉好多,但是有些乱,而且大家都理解为是在网站的根目录,这样据友友说并没有那么难的啦,我不知道怎么去实现,后来只能求助或者仍然寻找资料啦,昨天我是这样解决的,就总结一下吧。
二.下载服务器上Excel文件保存在本机
首先我们会涉及到两个View页面,在这里我举例的是Index和ShowDl,首先在Index页面上面有个要下载的按钮,我们点击按钮即可跳到下一个页面,即ShowDl,代码如下:
//第一个参数为显示的文本,第二个参数为Action的名字,第三个为Controller的名字 @Html.ActionLink("下载文件", "Show", "Download")
当我们跳转到ShowDl的Action之后,我们需要查询我们需要下载的文件在此页面上面,即代码如下:
public ActionResult ShowDl() { //文件路径配置在webconfig中的appconfig中,因此获取文件路径即可 string filePath = ConfigurationManager.AppSettings["Download"]; //获取文件的绝对路径以及文件名 string[] fPath = Directory.GetFiles(filePath); List<string> fileName = new List<string>(); //仅仅获取文件名 foreach (var item in fPath) { fileName.Add(Path.GetFileName(item)); } //创建一个ViewData,在view上面遍历文件名字 ViewData["fileName"] = fileName; return View(); }
View页面的显示文件名字如下:
<table> @{ List<string> fileName = ViewData["fileName"] as List<string>;} @if (fileName.Count > 0) { foreach (string item in fileName) { <tr> <td>文件名:</td> <td>@item</td> <td><input type="checkbox" class="dDown" value="@item" />选择下载</td> </tr> } } <tr> <td><input type="button" id="download" value="下载文件" onclick="Download()" /></td> <td><input type="button" id="allCheck" value="全选" onclick="checkAll()" /></td> </tr> </table>
<script> function Download() { var str = [];//定义一个数组 $('.dDown:checked').each(function () {//遍历每一个名字为dol的复选框,其中选中的执行函数 str.push($(this).val());//将选中的值添加到数组str中 }); $.ajax({ type: "POST", url: "/Home/DownloadFile", contentType: "application/json", data: JSON.stringify(str) }); }; function checkAll() { $('.dDown').each(function () { $(this).attr("checked", "checked"); //设置属性为全部选中 }); }; </script>
此时我们选择了在ShowDl页面上显示的所有文件的名字,然后我们在此页面上面设置了两个按钮,一个是点击按钮现在文件,一个是全选,当点击下载按钮时间,用的是ajax直接异步跳到下面的HomeController中DownloadFile,代码如下:
[HttpPost] public FileResult DownloadFile(List<string> list) { //获取服务器中的文件路径 string filePath = ConfigurationManager.AppSettings["Download"]; //要压缩的文件夹,把需要打包的文件存放在此文件夹 string dPath = @"E:文件"; //压缩后的文件存放路径 string destFile = @"E:文件Download"; if (list.Count > 1) { foreach (string fileName in list) { string sourceFileName = Path.Combine(filePath, fileName) + ".xls"; string destFileName = Path.Combine(dPath, fileName) + ".xls"; //true为覆盖同名文件 System.IO.File.Copy(sourceFileName, destFileName, true); } FileDown fileDown = new FileDown(); //返回压缩后的文件提供下载 fileDown.ZipFileFromDirectory(dPath, destFile, 9); //参数为文件存放路径,下载的文件格式,文件名字 return File(destFile, "application/octet-stream", Path.GetFileName(destFile)); } else { //单个文件下载,不需要打包 foreach (string fileName in list) { string sourceFileName = Path.Combine(filePath, fileName) + ".xls"; string destFileName = Path.Combine(dPath, fileName) + ".xls"; System.IO.File.Copy(sourceFileName, destFileName, true); } //参数为文件存放路径,下载的文件格式,文件名字 return File(destFile, "application/csv", Path.GetFileName(destFile)); } }
上面是在Action中实现了下载,其实这个友友也帮啦好多忙的,嘿嘿,首先说在WebConfig中配置但是在上面中调用了一位友友修改的方法,我就直接拿来用啦,蛮好用的,嘿嘿,而且我看了ZipFile类中的几个方法,下面是那个方法,我也贴出来啦,嘿嘿,又有看到不要介意哈。
/// 所有文件缓存 List<string> files = new List<string>(); /// 所有空目录缓存 List<string> paths = new List<string>(); /// <summary> /// 压缩目录(包括子目录及所有文件) /// </summary> /// <param name="rootPath">要压缩的根目录</param> /// <param name="destinationPath">保存路径</param> /// <param name="compressLevel">压缩程度,范围0-9,数值越大,压缩程序越高</param> public void ZipFileFromDirectory(string rootPath, string destinationPath, int compressLevel) { GetAllDirectories(rootPath); //得到当前路径的位置,以备压缩时将所压缩内容转变成相对路径。 string rootMark = rootPath + "\"; //Crc32校验 Crc32 crc = new Crc32(); //zip输出类 ZipOutputStream outPutStream = new ZipOutputStream(File.Create(destinationPath)); // 0-9程序的压缩,设置压缩程度 outPutStream.SetLevel(compressLevel); //将文件读入压缩流 foreach (string file in files) { FileStream fileStream = File.OpenRead(file); byte[] buffer = new byte[fileStream.Length]; fileStream.Read(buffer, 0, buffer.Length); //设置文件的一些参数 ZipEntry entry = new ZipEntry(file.Replace(rootMark, string.Empty)); entry.DateTime = DateTime.Now; entry.Size = fileStream.Length; fileStream.Close(); //计算Crc32检验码 crc.Reset(); crc.Update(buffer); //设置校验码 entry.Crc = crc.Value; //将当前文件的zip文件流写入输出流 outPutStream.PutNextEntry(entry); outPutStream.Write(buffer, 0, buffer.Length); } this.files.Clear(); foreach (string emptyPath in paths) { ZipEntry entry = new ZipEntry(emptyPath.Replace(rootMark, string.Empty) + "/"); outPutStream.PutNextEntry(entry); } this.paths.Clear(); outPutStream.Finish(); outPutStream.Close(); GC.Collect(); } /// <summary> /// 取得目录下所有文件及文件夹,分别存入files及paths /// </summary> /// <param name="rootPath">根目录</param> private void GetAllDirectories(string rootPath) { //获取所有的子目录 string[] subPaths = Directory.GetDirectories(rootPath); foreach (string path in subPaths) { //找到子目录并将当前目录的文件名存入List GetAllDirectories(path); } string[] files = Directory.GetFiles(rootPath); foreach (string file in files) { //将当前目录中的所有文件全名存入文件list this.files.Add(file); } //判断是否是空目录 if (subPaths.Length == files.Length && files.Length == 0) { //如果是空目录则记录空目录 this.paths.Add(rootPath); } }
好啦,就写到这里啦,嘿嘿,项目最后一个就是下载的啦,昨天上午已完成,坐等接下来的任务啦,加油加油,我不知道的太多啦,希望友友们知道的帮忙哈。。。