写在前面
上篇文章通过iframe实现了文件的无刷新上传。这篇我们将实现文件的下载与删除。
系列文章
[EF]vs15+ef6+mysql code first方式
[实战]MVC5+EF6+MySql企业网盘实战(2)——用户注册
[实战]MVC5+EF6+MySql企业网盘实战(3)——验证码
[实战]MVC5+EF6+MySql企业网盘实战(4)——上传头像
[实战]MVC5+EF6+MySql企业网盘实战(5)——登录界面,头像等比例压缩
[实战]MVC5+EF6+MySql企业网盘实战(5)——页面模板
[实战]MVC5+EF6+MySql企业网盘实战(5)——ajax方式注册
[实战]MVC5+EF6+MySql企业网盘实战(6)——ajax方式登录
[实战]MVC5+EF6+MySql企业网盘实战(7)——文件上传
[实战]MVC5+EF6+MySql企业网盘实战(8)——文件下载、删除
核心代码
上篇实现文件的上传,需要加上一段逻辑,判断上传的文件大小+网盘中所有文件的大小是否已经大于个人网盘的实际容量,如果大于则给予提示,所以,文件上传的代码修改后如下所示:
[HttpPost] public void UploadFile(string filePath) { UserInfo userInfo = Session["user"] as UserInfo; if (userInfo == null) { RedirectToAction("Login", "UserInfo"); } var files = Request.Files; if (files.Count > 0) { var file = files[0]; string fileName = file.FileName; Stream inputStream = file.InputStream; string fileSaveFolder = Request.MapPath("~/NetDisk/" + userInfo.UserName); if (!string.IsNullOrEmpty(filePath)) { fileSaveFolder = Path.Combine(fileSaveFolder, filePath); } //如果目标不存在,则创建 if (!Directory.Exists(fileSaveFolder)) { Directory.CreateDirectory(fileSaveFolder); } byte[] buffer = new byte[inputStream.Length]; //判断是否已经超出个人网盘大小 int myDiskSize = _myFileServiceRepository.FindAll(x => x.User.Id == userInfo.Id).Sum(x => x.FileSize); //如果已经超出网盘大小,则给出提示 if (myDiskSize + buffer.Length > userInfo.NetDiskSize) { AlertMsg("对不起,您的网盘空间不足,请清理后再次上传,或联系管理员进行扩容。", ""); return; } inputStream.Read(buffer, 0, buffer.Length); string strFileMd5 = MD5Helper.GetMD5FromFile(buffer); string fileSavePath = Path.Combine(fileSaveFolder, filePath); fileSavePath = Path.Combine(fileSaveFolder, fileName); //如果文件已经存在 if (System.IO.File.Exists(fileSavePath)) { //对文件进行重命名 fileName = ReNameHelper.FileReName(fileSavePath); fileSavePath = Path.Combine(fileSaveFolder, fileName); } file.SaveAs(fileSavePath); var currentUser = _userInfoServiceRepository.Find(x => x.Id == userInfo.Id); MyFile myFile = new MyFile() { FileMd5 = strFileMd5, ModifyDt = DateTime.Now, IsDelete = false, FileSize = buffer.Length, FilePath = "/NetDisk/" + userInfo.UserName + "/" + fileName, FileExt = Path.GetExtension(fileSavePath), CreateDt = DateTime.Now, FileName = fileName, FileIcon = GetFileIcon(Path.GetExtension(fileSavePath)), User = currentUser }; //保存数据库 _myFileServiceRepository.Add(myFile); _myFileServiceRepository.SaveChanges(); string json = new JavaScriptSerializer().Serialize(myFile); AlertMsg("上传成功", json); } }
今天发现一个bug,发现在路径存储的时候,如果文件名中有中文名称,则会出现乱码的问题,这里只能手动进行数据库字段的编码修改了。
下载的代码:
public void DownLoadFile(string fileId) { UserInfo userInfo = Session["user"] as UserInfo; if (userInfo == null) { RedirectToAction("Login", "UserInfo"); return; } if (string.IsNullOrEmpty(fileId)) { throw new ArgumentNullException("fileId is errror"); } int id = Convert.ToInt32(fileId); var findFile = _myFileServiceRepository.Find(x => x.Id == id); if (findFile == null) { AlertMsg("文件不存在", ""); return; } string filePath = Request.MapPath(findFile.FilePath); //以字符流的形式下载文件 FileStream fs = new FileStream(filePath, FileMode.Open); byte[] bytes = new byte[(int)fs.Length]; fs.Read(bytes, 0, bytes.Length); fs.Close(); Response.ContentType = "application/octet-stream"; //通知浏览器下载文件而不是打开 Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode(findFile.FileName, System.Text.Encoding.UTF8)); Response.BinaryWrite(bytes); Response.Flush(); Response.End(); }
<tbody role="alert" aria-live="polite" aria-relevant="all"> @{int i = 0;} @foreach (var item in Model) { i++; <tr class="i%2==0?'even':'odd'"> <td class=" even sorting_1"><img src="@item.FileIcon" alt="" />@item.FileName</td> <td class="center ">@item.FileSize 字节</td> <td class="center ">@item.ModifyDt</td> <td class="center "> <a class="btn btn-success" href="/Home/DownLoadFile?fileId=@item.Id"> <i class="glyphicon glyphicon-zoom-in icon-white"></i> 下载 </a> <a class="btn btn-info" href="#"> <i class="glyphicon glyphicon-edit icon-white"></i> 编辑 </a> <a class="btn btn-danger" href="#"> <i class="glyphicon glyphicon-trash icon-white"></i> 删除 </a> </td> </tr> } </tbody>
测试
完善动态创建的上传文件信息
//上传成功后,单击确定,更新刚刚拼接文件信息 function showMsg(msg, callbackInfo) { if (msg) { $(".modal-body").html(msg); //回调信息 $("#hdcallbackInfo").val(callbackInfo); console.log(callbackInfo); //为确定按钮注册单击事件,确定后更新拼接在列表上的文件信息 $('#fileListSure').click(function () { var fileInfo = $("#hdcallbackInfo").val(); console.log(fileInfo); fileInfo = JSON.parse(fileInfo); $("#fileDownLoad").attr("href", "/Home/DownLoadFile?fileId=" + fileInfo.Id); $("#fileName").html('<img src="' + fileInfo.FileIcon + '" id="fileicon" alt="" />' + fileInfo.FileName + ''); }); $("#myModal").modal("show"); }; };
$("#btnFile").change(function () { var files = this.files; for (var i = 0; i < files.length; i++) { var file = files[i]; console.log(file); $(' <tr class="odd"> <td class=" even sorting_1" id="fileName"><img src="/Content/Images/othertype.png" id="fileicon" alt="" />' + file.name + '</td><td class="center">' + file.size + ' 字节</td><td class="center ">' + CurentTime() + '</td><td class="center "> <a class="btn btn-success" href="#" id="fileDownLoad"><i class="glyphicon glyphicon-zoom-in icon-white"></i> 下载 </a><a class="btn btn-info" href="#" id="fileEdit"> <i class="glyphicon glyphicon-edit icon-white"></i> 编辑 </a><a class="btn btn-danger" href="#"><i class="glyphicon glyphicon-trash icon-white" id="fileDelete"></i> 删除 </a> </td></tr>').appendTo($('#fileList tbody')); }; $('#fileForm').submit(); });
删除,这里进行逻辑删除,为以后客户端的开发考虑,如果是客户端进行上传,可以采用md5的比对,如果文件已经存在,则复制一条信息即可,可实现文件的秒传。
public void DeleteFile(string fileId) { UserInfo userInfo = Session["user"] as UserInfo; if (userInfo == null) { RedirectToAction("Login", "UserInfo"); return; } if (string.IsNullOrEmpty(fileId)) { throw new ArgumentNullException("fileId is errror"); } int id = Convert.ToInt32(fileId); var findFile = _myFileServiceRepository.Find(x => x.Id == id); if (findFile == null) { AlertMsg("文件不存在", ""); return; } findFile.IsDelete = true; _myFileServiceRepository.Update(findFile); int count = _myFileServiceRepository.SaveChanges(); if (count > 0) { var response = new { code = 4, fileId = findFile.Id }; Response.Write(new JavaScriptSerializer().Serialize(response)); } }
前端代码
@model IEnumerable<Wolfy.NetDisk.Model.MyFile> @{ ViewBag.Title = "FileList"; Layout = "~/Views/Shared/_Layout.cshtml"; } <button id="btnUpload" class="btn-primary">上传文件</button> <button class="btn-primary">新建文件夹</button> <div class="box-content" id="fileList"> <div class="dataTables_wrapper" role="grid"> <table id="fileList" class="table table-striped table-bordered responsive" id="DataTables_Table_0" aria-describedby="DataTables_Table_0_info"> <thead> <tr role="row"> <th class="sorting_asc" role="columnheader" tabindex="0" aria-controls="DataTables_Table_0" rowspan="1" colspan="1" aria-sort="ascending" aria-label="Username: activate to sort column descending" style=" 312px;">文件名</th> <th class="sorting" role="columnheader" tabindex="0" aria-controls="DataTables_Table_0" rowspan="1" colspan="1" aria-label="Role: activate to sort column ascending" style=" 144px;">大小</th> <th class="sorting" role="columnheader" tabindex="0" aria-controls="DataTables_Table_0" rowspan="1" colspan="1" aria-label="Date registered: activate to sort column ascending" style=" 263px;">修改日期</th> <th class="sorting" role="columnheader" tabindex="0" aria-controls="DataTables_Table_0" rowspan="1" colspan="1" aria-label="Actions: activate to sort column ascending" style=" 549px;">操作</th> </tr> </thead> <tbody role="alert" aria-live="polite" aria-relevant="all"> @{int i = 0;} @foreach (var item in Model) { i++; <tr class="i%2==0?'even':'odd'" id="tr-@item.Id"> <td class=" even sorting_1"><img src="@item.FileIcon" alt="" />@item.FileName</td> <td class="center ">@item.FileSize 字节</td> <td class="center ">@item.ModifyDt</td> <td class="center "> <a class="btn btn-success" href="/Home/DownLoadFile?fileId=@item.Id"> <i class="glyphicon glyphicon-zoom-in icon-white"></i> 下载 </a> <a class="btn btn-info" href="#"> <i class="glyphicon glyphicon-edit icon-white"></i> 编辑 </a> <a class="btn btn-danger" href="javascript:void(0)" onclick="deleteFile(@item.Id)"> <i class="glyphicon glyphicon-trash icon-white"></i> 删除 </a> </td> </tr> } </tbody> </table> </div> </div> <form action="UploadFile" id="fileForm" method="post" enctype="multipart/form-data" target="fileFrame"> <input type="file" accept="*/*" style="display:none" id="btnFile" name="fileData" /> <input type="hidden" id="hdFilePath" name="filePath" value="" /> <input type="hidden" id="hdcallbackInfo" name="name" value="" /> </form> <iframe style="display:none" name="fileFrame" id="fileFrame"></iframe> <script> //上传成功后,单击确定,更新刚刚拼接文件信息 function showMsg(msg, callbackInfo) { if (msg) { $(".modal-body").html(msg); //回调信息 $("#hdcallbackInfo").val(callbackInfo); console.log(callbackInfo); //为确定按钮注册单击事件,确定后更新拼接在列表上的文件信息 $('#fileListSure').click(function () { var fileInfo = $("#hdcallbackInfo").val(); console.log(fileInfo); fileInfo = JSON.parse(fileInfo); $("#fileDownLoad").attr("href", "/Home/DownLoadFile?fileId=" + fileInfo.Id); $("#fileName").html('<img src="' + fileInfo.FileIcon + '" id="fileicon" alt="" />' + fileInfo.FileName + ''); }); $("#myModal").modal("show"); }; }; function deleteFile(fileId) { console.log(fileId); $.getJSON("/Home/DeleteFile?fileId="+fileId,function(data){ console.log(data.code); if (data.code==4) { $("#tr-"+fileId).remove(); }; }); }; function CurentTime() { var now = new Date(); var year = now.getFullYear(); //年 var month = now.getMonth() + 1; //月 var day = now.getDate(); //日 var hh = now.getHours(); //时 var mm = now.getMinutes(); //分 var clock = year + "-"; if (month < 10) clock += "0"; clock += month + "-"; if (day < 10) clock += "0"; clock += day + " "; if (hh < 10) clock += "0"; clock += hh + ":"; if (mm < 10) clock += '0'; clock += mm; return (clock); }; $('#btnUpload').click(function () { $("#btnFile").click(); }); $("#btnFile").change(function () { var files = this.files; for (var i = 0; i < files.length; i++) { var file = files[i]; console.log(file); $(' <tr class="odd"> <td class=" even sorting_1" id="fileName"><img src="/Content/Images/othertype.png" id="fileicon" alt="" />' + file.name + '</td><td class="center">' + file.size + ' 字节</td><td class="center ">' + CurentTime() + '</td><td class="center "> <a class="btn btn-success" href="#" id="fileDownLoad"><i class="glyphicon glyphicon-zoom-in icon-white"></i> 下载 </a><a class="btn btn-info" href="#" id="fileEdit"> <i class="glyphicon glyphicon-edit icon-white"></i> 编辑 </a><a class="btn btn-danger" href="#"><i class="glyphicon glyphicon-trash icon-white" id="fileDelete"></i> 删除 </a> </td></tr>').appendTo($('#fileList tbody')); }; $('#fileForm').submit(); }); </script>
总结
完善上传逻辑,并实现文件的下载与逻辑删除,下一步将实现新建文件夹,并合并新建文件夹与上传文件的逻辑。