功能点:

1. 使用.net core 2.0 实现文件上传

2. 使用webuploader实现单文件,多文件上传

3. 使用webuploader实现大文件的分段上传。

4. 使用webuploader与FastDfs实现文件上传。

5. 通过依赖注入可以很方便地实现本地文件存储切换为FastDfs

主要功能:

直接上代码:

1. 使用.net core 2.0 实现文件上传

        public ActionResult Upload(IFormCollection files)
{
var result = new UploadResult(); foreach (var item in files.Files)
{
#region 把文件流转化为字节流
byte[] buffer = new byte[item.Length]; Stream fs = item.OpenReadStream(); fs.Read(buffer, , buffer.Length);
#endregion UploadConfig config = new UploadConfig
{
Buffer = buffer,
FileName = item.FileName,
Chunked = files.Keys.Contains("chunk"),
PreviosName = files["previosName"]
}; result = _provider.Upload(config);
}
return Json(result);
}

这里要注意参数,使用的是IFormCollection,没有使用IFormFile,使用后者的话,不能接收前台发送的自定义参数。虽然我用了fforeach循环,但实现上它的files count只有一个,不管前台发送的是一个文件,还是多个文件,这点还要研究一下,是不是有配置。

        private readonly IFileSystemProvider _provider;

        public HomeController(IFileSystemProvider provider)
{
_provider = provider; }
IFileSystemProvider 为定义的接口,分别有本地文件存储,和分布式文件存储两种实现方式,后面会奉上代码。

2. 使用webuploader实现单文件,多文件上传
这里主要上前台代码:
        // 实例化
uploader = WebUploader.create({
pick: {
id: '#filePicker',
label: '点击选择文件'
},
dnd: '#dndArea',
paste: '#uploader',
swf:'lib/webuploader/Uploader.swf',
chunked: true, //分片处理大文件
chunkSize: 1 * 1024 * 1024,
server: home/upload,
disableGlobalDnd: true,
threads: 1, //上传并发数
fileNumLimit: 300,
compress: false, //图片在上传前不进行压缩
fileSizeLimit: 1024 * 1024 * 1024, // 1024 M
fileSingleSizeLimit: 1024 * 1024 * 1024 // 1024 M
});

初始化webuploader这里要注意threads我想的是1,如果分段上传,几个分段同时发送的话,后台如果写入是个问题,特别是使用fastdfs, .net版本的sdk还不支持指定位置写入的功能。

注意到一个事件:它是实现分段上传重中之重

        uploader.on('uploadAccept', function (file, response) {
if (file.chunk + 1 !== file.chunks) {
$.extend(uploader.options.formData, { previosName: response.filePath });
} else {
$.extend(uploader.options.formData, { previosName: "" });
}
return true;
});

这里着重解释一下。看到网上关于文件分段上传,都是在服务器端用临时文件记录着文件上传的地址,当有分段信息到达时,会查询临时文件,取出文件地址,然后再往这个地址追加文件流。

这样增加了服务器端的复杂度,而且如果是分布式部署的话,会存在找到临时文件的问题,进而会考虑到数据库和分布式缓存的解决方案,更加复杂了。

这里简单说明一下解决思路:

1) 后台:第一段上传成功后,返回文件地址。如代码的 return Json(result);

2) 前台:使用uploadAccept事件接收文件信息和后台返回地址。

3)前台:在uploadAccept事件中:添加往后台发送的参数previosName:第一段返回的文件地址。

这里要注意如果是多个文件上传的话,第二个文件的第一个分段不能带有第一个文件的上传地址,如上代码所示

4) 后台:如上面的代码所示,接收前台发送的文件地址,做文件的追加,即可。

3. 使用webuploader实现大文件的分段上传。

下面是服务端的代码:

        public UploadResult Upload(UploadConfig config)
{
//相对路径
string path = GetFileName(config); //根据路径创建一个新的文件,并在指定位置写入字节,如果文件已存在,就追加
using (FileStream fs = File.OpenWrite(Path.Combine(_option.RootFilePath, path)))
{
if (fs.CanWrite)
{
fs.Seek(fs.Length, SeekOrigin.Current);
fs.Write(config.Buffer, , config.Buffer.Length);
fs.Flush();
fs.Close();
}
} return new UploadResult { FilePath = path, OriginalName = config.FileName };
} private string GetFileName(UploadConfig config)
{
string path; if (string.IsNullOrEmpty(config.PreviosName))
{
path = Path.Combine(subDirectory, $"{GuidTo16String()}.{config.FileName}"); //返回的相对路径和文件名 CheckSavePath();
}
else
{
path = config.PreviosName;
if (string.IsNullOrEmpty(config.PreviosName))
{
throw new ArgumentNullException("PreviosName 参数不能为空");
}
} return path;
} private string CheckSavePath()
{
var path = Path.Combine(_option.RootFilePath, subDirectory); // 如何路径不存在,就创建文件路径
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
} return path;
}

这里关注一下GetFileName方法:代码很简单,就不做说明了。

4. 使用webuploader与FastDfs实现文件上传

前端代码和服务端的action的代码是一样的。主要是写文件的方式不一样,主要代码如下:

        public UploadResult Upload(UploadConfig config)
{
if (string.IsNullOrEmpty(config.PreviosName))
{
var fileName = string.Empty;
var storageNode = _client.GetStorageNode(config.GroupName); if (!config.Chunked)
{
fileName = _client.UploadFile(storageNode, config.Buffer, Path.GetExtension(config.FileName));
}
else
{
//分段上传需要调用这个方法
fileName = _client.UploadAppenderFile(storageNode, config.Buffer, Path.GetExtension(config.FileName));
} return new UploadResult { FilePath = fileName, OriginalName = config.FileName };
}
else
{
//分段上传:需要提供上传GroupName, 文件上传地址PreviosName,文件上传内容filebody
//续传 地址config.PreviosName
_client.AppendFile(config.GroupName, config.PreviosName, config.Buffer); return new UploadResult { FilePath = config.PreviosName, OriginalName = config.FileName };
}
}

这里注意分段上传的文件,第一段上传使用的方法是UploadAppenderFile,后续使用的是AppendFile。

连接FastDfs的代码如下:

    public class FastDfsClientProvider : IFastDfsClientProvider
{
private readonly FastDfsOption _options; public FastDfsClientProvider(FastDfsOption options)
{
_options = options;
} public FastDfsClient GetClient()
{
return new FastDfsClient(new List<IPEndPoint>
{
new IPEndPoint(IPAddress.Parse(_options.IpAddress), _options.Port)
});
}
}

5. 通过依赖注入可以很方便地实现本地文件存储切换为FastDfs

代码如下:

        public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(); services.AddTransient<IFileSystemProvider>(m=> {
IHostingEnvironment env = m.GetService<IHostingEnvironment>(); LocalFsOption lOption = new LocalFsOption
{
RootFilePath = Path.Combine(env.ContentRootPath, "Files")
};
return new LocalFsProvider(lOption);
});
}

如果想换实现的话 改一个return new LocalFsProvider(lOption),配置一下参数就行了。

部分代码参考博友,找不到出处了,请凉解。

Asp.Net Core 2.0 WebUploader FastDfs 文件上传 分段上传的更多相关文章

  1. 基础教程:上传/下载ASP.NET Core 2.0中的文件

    问题 如何上传和下载ASP.NET Core MVC中的文件. 解 在一个空的项目中,更新 Startup 类以添加MVC的服务和中间件. publicvoid ConfigureServices( ...

  2. 用VSCode开发一个asp.net core2.0+angular5项目(5): Angular5+asp.net core 2.0 web api文件上传

    第一部分: http://www.cnblogs.com/cgzl/p/8478993.html 第二部分: http://www.cnblogs.com/cgzl/p/8481825.html 第三 ...

  3. ASP.NET Core 1.0中实现文件上传的两种方式(提交表单和采用AJAX)

    Bipin Joshi (http://www.binaryintellect.net/articles/f1cee257-378a-42c1-9f2f-075a3aed1d98.aspx) Uplo ...

  4. [译]ASP.NET Core 2.0 机密配置项

    问题 如何在ASP.NET Core 2.0中保存机密配置项(不用将其暴露给源代码管理器)? 答案 创建一个ASP.NET Core 2.0空项目,在项目节点上点击右键,并点击菜单项 - 管理用户机密 ...

  5. 探索 ASP.Net Core 3.0系列五:引入IHostLifetime并弄清Generic Host启动交互

    前言:在本文中,我将介绍如何在通用主机之上重新构建ASP.NET Core 3.0,以及由此带来的一些好处. 同时也展示了3.0中引入新的抽象类IHostLifetime,并描述了它在管理应用程序(尤 ...

  6. ASP.NET Core 1.0 静态文件、路由、自定义中间件、身份验证简介

    概述 ASP.NET Core 1.0是ASP.NET的一个重要的重新设计. 例如,在ASP.NET Core中,使用Middleware编写请求管道. ASP.NET Core中间件对HttpCon ...

  7. [译]ASP.NET Core 2.0 本地文件操作

    问题 如何在ASP.NET Core 2.0中受限地访问本地目录和文件信息? 答案 新建一个空项目,修改Startup类,添加访问本地文件所需的服务: public void ConfigureSer ...

  8. ASP.NET Core 1.0: 指定Static File中的文件作为default page

    指定一个网站的default page是很容易的事情.譬如IIS Management中,可以通过default page来指定,而默认的index.html, index.htm之类,则早已经被设置 ...

  9. ASP.NET Core 1.0 开发记录

    官方资料: https://github.com/dotnet/core https://docs.microsoft.com/en-us/aspnet/core https://docs.micro ...

随机推荐

  1. &lt;Android 开源库&gt; GreenDAO 使用方法具体解释&lt;译文&gt;

    简单介绍 greenDAO是一个开源的Android ORM,使SQLite数据库的开发再次变得有趣. 它减轻了开发者处理底层的数据库需求,同一时候节省开发时间. SQLite是一个非常不错的关系型数 ...

  2. oracle查看被锁的表和被锁的进程,杀掉进程

    -- 1. 查看被锁的表 SELECT p.spid, a.serial#, c.object_name, b.session_id, b.oracle_username,b.os_user_name ...

  3. html读写excle文档

    import.html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> & ...

  4. 使用DAO工厂创建实现类对象

    首先分析DAO模式中的每一部分 VO(对象实体):这个类成员变量与数据库中每个字段一一对应,同时提供了相应是set和get方法来设置或取得数值.这个类一般是通过IDE自动生成的 DAO(数据访问接口) ...

  5. Angular 笔记系列(二)数据绑定

    数据绑定这块儿没啥说的,简单两个例子带过了. Hello World: <!DOCTYPE html> <html ng-app> <head> <title ...

  6. mysql数据库从删库到跑路之mysq索引

    一 介绍 为何要有索引? 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,在生产环境中,我们遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,因此对查询语句 ...

  7. 在Windows下使用Dev-C++开发基于pthread.h的多线程程序【转】

    在Windows下使用Dev-C++开发基于pthread.h的多线程程序[转]     在Windows下使用Dev-C++开发基于pthread.h的多线程程序   文章分类:C++编程     ...

  8. 干货!Jenkins下配置findbugs、pmd及checkstyle实现代码自动检测

    配置前提: 对于maven项目来说,需要在pom.xml文件的<build><plugins>添加配置</plugins></build> 网上有些地方 ...

  9. spoj1812 LCS2 - Longest Common Substring II

    地址:http://www.spoj.com/problems/LCS2/ 题面: LCS2 - Longest Common Substring II no tags  A string is fi ...

  10. Docker+.Net Core 的那些事儿-4.还有这种操作!?

    1.通过docker run -v命令映射工作目录 通过一系列上述操作,我们可以发现我们的发布是基于镜像的,也就是说,在后期的迭代过程中,如果有些代码修改,我们就不得不删除旧的容器和镜像,dotnet ...