写在前面
周末了,在家继续折腾网盘,今天实现网盘文件的上传。
系列文章
[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方式登录
业务逻辑
今天突然发现,用户类中少一个个人网盘的默认大小,这里添加一个字段,记录个人网盘的大小,默认给它1G的空间,在数据库中以字节存储。1G=1073741842字节。所以现在用户信息类现在是这个样子。
/// <summary> /// 用户信息类 /// </summary> public class UserInfo { /// <summary> /// 编号 /// </summary> [Key] public int Id { set; get; } /// <summary> /// 用户头像地址 /// </summary> [StringLength(512)] [Display(Name = "头像")] public string Header { set; get; } /// <summary> /// 姓名 /// </summary> [MaxLength(64, ErrorMessage = "网名长度不得超过32个字符")] [Required(ErrorMessage = "请填写您的名称")] [Display(Name = "姓名")] public string UserName { set; get; } /// <summary> /// 密码 /// </summary> [StringLength(32, ErrorMessage = "密码长度不得超多32位")] [Required] [Display(Name = "密码")] public string Pwd { set; get; } /// <summary> /// 性别 /// </summary> [Display(Name = "性别")] public GenderType Gender { set; get; } /// <summary> /// 所属部门id /// </summary> [Display(Name = "部门")] public Department Department { set; get; } /// <summary> /// 添加时间 /// </summary> [Display(Name = "创建日期")] public DateTime CreateDt { set; get; } /// <summary> /// 添加时间 /// </summary> [Display(Name = "登录日期")] public DateTime LoginDt { set; get; } /// <summary> /// 登出时间 /// </summary> [Display(Name = "登录日期")] public DateTime LoginOutDt { set; get; } /// <summary> /// 网盘默认大小 1G=1073741842字节 /// </summary> private int _netDiskSize = 1073741842; public int NetDiskSize { get { return _netDiskSize; } set { _netDiskSize = value; } } }
文件信息类MyFile
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Wolfy.NetDisk.Model { /// <summary> /// 我的文件信息 /// </summary> public class MyFile { [Key] public int Id { set; get; } [Display(Name = "文件路径")] [StringLength(int.MaxValue)] public string FilePath { set; get; } [Display(Name = "文件名")] [StringLength(1024)] public string FileName { set; get; } [Display(Name = "文件扩展名")] [StringLength(8)] public string FileExt { set; get; } [Display(Name = "文件图标")] [StringLength(32)] public string FileIcon { set; get; } [Display(Name = "文件大小")] public int FileSize { set; get; } [Display(Name = "文件MD5")] [StringLength(32)] public string FileMd5 { set; get; } [Display(Name = "文件修改时间")] public DateTime ModifyDt { set; get; } [Display(Name = "文件上传时间")] public DateTime CreateDt { set; get; } [Display(Name = "文件是否删除")] public bool IsDelete { set; get; } [Display(Name = "文件所属")] public virtual UserInfo User { set; get; } } }
其他的IDAL,IBLL,BLL,DAL层的代码与userInfo的基本类似,这里不再贴出。
这里使用iframe进行无刷新上传。
<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>
回调js方法
function showMsg(msg, callbackInfo) { if (msg) { $(".modal-body").html(msg); //回调信息 $("#hdcallbackInfo").val(callbackInfo); $("#myModal").modal("show"); }; };
服务端
[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]; 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); } } private void AlertMsg(string msg, string fileJson) { Response.ContentType = "text/html"; Response.Write("<script>parent.showMsg('" + msg + "','" + fileJson + "');</script>"); } private string GetFileIcon(string fileExt) { string fileIconPath = "/Content/Images/"; switch (fileExt.ToLower()) { case ".doc": case ".docx": fileIconPath += "DocType.png"; break; case ".xlx": case ".xlxs": fileIconPath += "XlsType.png"; break; case ".ppt": case ".pptx": fileIconPath += "PptType.png"; break; case ".pdf": fileIconPath += "PdfType.png"; break; case ".apk": fileIconPath += "ApkType.png"; break; case ".dwt": case ".dwg": case ".dws": case ".dxf": fileIconPath += "CADType.png"; break; case ".exe": fileIconPath += "ExeType.png"; break; case ".png": case ".gif": case ".jpg": fileIconPath += "ImgType.png"; break; case ".txt": fileIconPath += "TxtType.png"; break; case ".bt": fileIconPath += "TorrentType.png"; break; case ".rmvb": case ".avi": case ".flv": fileIconPath += "VideoType.png"; break; case ".zip": case ".7z": case ".rar": fileIconPath += "MusicType.png"; break; case ".mp3": fileIconPath += "MusicType.png"; break; default: fileIconPath += "OtherType.png"; break; } return fileIconPath; }
大概逻辑是,在服务端根据用户名创建一个目录,并且判断是否已经存在该文件,如果个人网盘中有该文件了则对其自动重命名,比如1.txt,则重命名后的名称为1(1).txt,文件及文件夹重命名的方法在之前的文章中写了一个工具类,这里直接拿来使用了。
地址:[工具类]文件或文件夹xx已存在,则重命名为xx(n)(2)
测试:
上传成功后,将信息写入隐藏域中,方便其他地方进行使用。
总结
这里使用了iframe的无刷新上传方式,没有使用插件。考虑到有移动端的访问,一般的上传插件是基于flash的,导致兼容性不是很好。