[实战]MVC5+EF6+MySql企业网盘实战(7)——文件上传

时间:2022-09-21 14:16:59

写在前面

周末了,在家继续折腾网盘,今天实现网盘文件的上传。

系列文章

[EF]vs15+ef6+mysql code first方式

[实战]MVC5+EF6+MySql企业网盘实战(1)

[实战]MVC5+EF6+MySql企业网盘实战(2)——用户注册

[实战]MVC5+EF6+MySql企业网盘实战(3)——验证码

[实战]MVC5+EF6+MySql企业网盘实战(4)——上传头像

[Bootstrap]modal弹出框

[实战]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)

测试:

[实战]MVC5+EF6+MySql企业网盘实战(7)——文件上传

[实战]MVC5+EF6+MySql企业网盘实战(7)——文件上传

上传成功后,将信息写入隐藏域中,方便其他地方进行使用。

总结

这里使用了iframe的无刷新上传方式,没有使用插件。考虑到有移动端的访问,一般的上传插件是基于flash的,导致兼容性不是很好。