文件下载、删除

写在前面

上篇文章通过iframe实现了文件的无刷新上传。这篇我们将实现文件的下载与删除。

核心代码

上篇实现文件的上传,需要加上一段逻辑,判断上传的文件大小+网盘中所有文件的大小是否已经大于个人网盘的实际容量,如果大于则给予提示,所以,文件上传的代码修改后如下所示:


     [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="width: 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="width: 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="width: 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="width: 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>

总结

完善上传逻辑,并实现文件的下载与逻辑删除,下一步将实现新建文件夹,并合并新建文件夹与上传文件的逻辑。