写在前面
周末了,在家继续折腾网盘,今天实现网盘文件的上传。
系列文章
[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的,导致兼容性不是很好。