.net core 6.0 mvc js对文件分片上传文件+控制器合并文件保存

js,通过ajax将文件分片提交

//获取文件信息(以上传图片为例)
//生成Blob的图片格式
var Imginfo=图片转为Blob格式信息;
//文件上传控制器路径
var
upload_url="XXXXXX";
/** * 文件上传入口,进行匹配计算文件上传大小然后上传 * */ function usk_upload_file_in(file) { var l = file.size; var step = _cnf_up_one_set.up_one_length; //获取文件分片总片数 var total_blob_num = Math.ceil(l / step); _cnf_up_one_set._one_total_num = total_blob_num; var _start = 0; var _end = 0; usk_callback(0, ""); _cnf_up_one_set._one_blob_num = 1; usk_upload_file_one(file); } /** * 文件上传,递归调用上传文件片 * */ function usk_upload_file_one(file) { var l = file.size; if (_cnf_up_one_set._one_blob_num > _cnf_up_one_set._one_total_num) { return; } var step = _cnf_up_one_set.up_one_length; _start = (_cnf_up_one_set._one_blob_num - 1) * step; _end = _start + step; if (_end >= l) { _end = l; } _cnf_up_one_set._one_blob_data = usk_cutfile_in(file, _start, _end); usk_upload_file(_cnf_up_one_set._one_blob_data, file); _cnf_up_one_set._one_blob_num++; setTimeout(function () { usk_upload_file_one(file); }, 1); //usk_upload_file_one(file);  } /** * 图片切割 * */ function usk_cutfile_in(file, s, e) { //文件分隔 var file_blob = file.slice(s, e); _cnf_up_one_set._one_start = s; _cnf_up_one_set._one_end = e; return file_blob; };
/** * 进行文件上传 * */ function usk_upload_file(blob, file) { //创建FormData对象 //FormData对象用于存储待上传的文件和相关信息。你需要将选定的Blob文件与该对象进行关联,以便在发送XHR请求时传递给服务器。 var form_data = new FormData(); form_data.append('file', blob); var ruladd2 = "&size=" + file.size + "&index=" + _cnf_up_one_set._one_blob_num + "&total=" + _cnf_up_one_set._one_total_num + "&fname=" + encodeURI(file.name); ruladd2 += "&guid=" + _cnf_up_one_set._up_one_guid ruladd2 = upload_url + ruladd2; $.ajax({ url: ruladd2, type: 'post', async: false, dataType: "json",//返回json数据类型 data: form_data, contentType: false,//似乎会默认转为:multipart/form-data processData: false, success: function (data) { var result = data.result; if (result < 0) { _layer.close(_cnf_up_one_set._one_loading_id); _layer.msg(data.msg, { icon: 2, time: 2000 }); } //#region 1.上传中 if (result == 1) { //上传中 // 进度条和状态设置 if (_cnf_up_one_set._one_total_num == 1) { progress = 100; } else { progress = (Math.min(100, (_cnf_up_one_set._one_blob_num / _cnf_up_one_set._one_total_num) * 100)).toFixed(2); } usk_callback(progress, "上传中"); form_data = ""; } //#endregion //#region 2.文件上传完成 if (result == 0) { _layer.close(_cnf_up_one_set._one_loading_id); //上传完成 _cnf_up_one_set._one_is_stop = 1; // 进度条 progress = 100; //每次清空 form_data = ""; usk_callback(progress, data.msg); } //#endregion }, error: function (data) { _layer.close(_cnf_up_one_set._one_loading_id); usk_callback(-1, "系统未知错误"); return; } }) }

控制器

/// <summary>
/// 获取上传文件
/// </summary>
/// <returns></returns>
public IActionResult UploadFileBlock([FromForm(Name = "file")] List<IFormFile> files)
{
    //获取上传文件 
    //获取上传文件的基本信息
    URLTools.UsURLToObjectOnly(FileBlob_entity, false);
    if (files.Count > 0)
    {
        //保存至分片文件夹
        //临时保存分块的目录
        _apiresult = SaveFile(files[0], FileBlob_entity);
    }
    USTemp = UsJsonTools.SerializeObject(_apiresult);
    return Content(USTemp);
}
 /// <summary>
 /// 上传保存文件
 /// </summary>
 /// <param name="file">文件</param>
 /// <param name="FileBlob_entity"></param>
 public APIResult SaveFile(IFormFile file, FileBlob FileBlob_entity)
        {
            string savepath = "";
            //判断是否存在,如果不存在自动创建 物理路径
            var filepath = Directory.GetCurrentDirectory();
            //文件存储路径
            var sSavePath = "";
            //文件分片临时存储文件夹
         
            //var genurl = System.AppDomain.CurrentDomain.BaseDirectory;
            string genurl = ToolsBasic.UsPath("");
            string sBaseDir = genurl+ "/upload/headImg/" + FileBlob_entity.guid;
            if (!Directory.Exists(sBaseDir))
            {
                Directory.CreateDirectory(sBaseDir);
            }
            //保存文件
            //本地保存路径
            sSavePath = sBaseDir + "/" + FileBlob_entity.guid + FileBlob_entity.index;
            //判断文件的存在
            var sese = System.IO.File.Exists(sSavePath);
            if (System.IO.File.Exists(sSavePath))
            {
                //存在文件
            }
            else
            {
                //不存在文件、保存本地
                using (FileStream fs = new FileStream(sSavePath, FileMode.Create))
                {
                    file.CopyTo(fs);
                    fs.Flush();
                }
            }
            _apiresult.result = 1;//上传中
            //最后一片上传成功进行合并
            if (FileBlob_entity.index.Ext_ToInt() == FileBlob_entity.total.Ext_ToInt())
            {
                savepath =  "/upload/headImg/" + DateTime.Now.ToString("yyyyMM");
                if (!Directory.Exists(genurl+savepath))
                {
                    Directory.CreateDirectory(genurl + savepath);
                }
                savepath = savepath + "/I-"+DateTime.Now.ToString("yyyyMMddhhmmss")+".jpg";
                MergeFileAsync(sBaseDir, genurl + savepath);
                _apiresult.result = 0;//上传完成
            }
            _apiresult.msg = savepath;
            _apiresult.data = FileBlob_entity;
            return _apiresult;
        }


 /// <summary>
 /// 合并分片的文件
 /// </summary>
 /// <param name="sBaseDir">临时文件夹</param>
 private async Task MergeFileAsync(string sBaseDir, string savepath)
        {
            //获得下面的所有文件
            var files = Directory.GetFiles(sBaseDir);
            //最终的文件名(demo中保存的是它上传时候的文件名,实际操作肯定不能这样)
            using (var fs = new FileStream(savepath, FileMode.Create))
            {
                //排一下序,保证从0-N Write
                var fileParts = files.OrderBy(x => x.Length).ThenBy(x => x);
                foreach (var part in fileParts)
                {
                    var bytes = await System.IO.File.ReadAllBytesAsync(part);
                    await fs.WriteAsync(bytes, 0, bytes.Length);
                    bytes = null;
                    //删除分块
                    System.IO.File.Delete(part);
                }
                await fs.FlushAsync();
                fs.Close();
                //删除临时文件夹和分片文件
                Directory.Delete(sBaseDir);
            }
}
  /// <summary>
    /// 文件分片上传信息
    /// </summary>
    public class FileBlob
    {
     
        /// <summary>
        /// 当前上传文件第几片
        /// </summary>
        public string index { get; set; }
        /// <summary>
        ///文件总大小
        /// </summary>
        public string size { get; set; }
        /// <summary>
        /// 文件总片数
        /// </summary>
        public string total { get; set; }
        //文件名
        public string fname { get; set; }
        /// <summary>
        /// guid
        /// </summary>
        public string guid { get; set; }
    }

执行过程;

上传时若文件大于设置的文件片大小,js进行切割,后端将其临时存在一个文件夹内;

 待全部文件片上传完后,将临时文件夹里的文件合并,然后删除这个临时文件

 文件片段上传成功后删除放置文件片的临时文件

查看目录,图片已经上传成功

遇到问题:

.net core 6.0 mvc上传文件位置

主文件夹下的\bin\Debug\net6.0

 文件访问不了问题

在startup配置

#region 让upload文件夹可以外部访问

string sUploadPath = "/upload";
string sFDir =ToolsBasic.UsPath(sUploadPath);
if (!Directory.Exists(sFDir))
{
    Directory.CreateDirectory(sFDir);
}
app.UseStaticFiles(new StaticFileOptions
{
    FileProvider = new PhysicalFileProvider(sFDir),
    RequestPath = sUploadPath
});

#endregion
public static string UsPath(string sPath)
{
    //程序集的基目录的文件路径。E:\文件PPT\文件PPT\oneself\SystemProjectOne\SystemProjectOne\SystemProjectOne\bin\Debug\net6.0\
     string baseDirectory = AppContext.BaseDirectory;
     string text = sPath;
     text = Path.Combine(baseDirectory + sPath);
     return Path.GetFullPath(text);
}

 参考文献:

https://www.cnblogs.com/GoatRoc/p/16192506.html
https://blog.csdn.net/allenwdj/article/details/103383460

posted @ 2023-07-08 16:53  じ逐梦  阅读(252)  评论(0)    收藏  举报