.NET文件上传服务设计

前言

在b站学习了一个后端小项目,然后发现这个文件上传设计还挺不错,来实现讲解一下。

项目结构如下:

基于策略+工厂模式实现文件上传服务

枚举

在Model层创建即可

    public enum UploadMode
{
Local = 1, //本地上传
Qiniu = 2 //七牛云上传
}

第一步:创建文件策略和工厂

在Service层中创建FileStrategy文件夹,在该文件夹下分别创建StrategyQiNiuStrategyLocalStrategyFileFactoryFileContext

Strategy 文件操作抽象类

/// <summary>
/// 文件操作抽象类
/// </summary>
public abstract class Strategy
{
public abstract Task<string> Upload(List<IFormFile> formFiles);
}

LocalStrategy 本地策略

继承Strategy 文件操作抽象类并实现他里面的方法

后续要实现该方法

public class LocalStrategy:Strategy
{
public override async Task<string> Upload(List<IFormFile> formFiles)
{
throw new NotImplementedException();
}
}

QiNiuStrategy 七牛云策略

同上

public class QiNiuStrategy:Strategy
{
public override async Task<string> Upload(List<IFormFile> formFiles)
{
throw new NotImplementedException();
}
}

FileContext 上下文

在策略模式中通过上下文调用具体的策略

这里的好处就是我如果new LocalStrategy则是本地上传服务,如果是new QiNiuStrategy则是七牛云上传,详情看下方工厂的设计

/// <summary>
/// 上下文,通过这个来调用具体的策略
/// </summary>
public class FileContext
{
private Strategy _strategy;
private List<IFormFile> _formFiles; public FileContext(Strategy strategy, List<IFormFile> formFiles)
{
_formFiles = formFiles;
_strategy = strategy;
} public async Task<string> ContextInterface()
{
return await _strategy.Upload(_formFiles);
}
}

FileFactory 工厂

通过工厂去负责对象的实例化

枚举的作用就来了,更据枚举去判断实例化那一个对象

/// <summary>
/// 工厂类,负责对象的实例化
/// </summary>
public class FileFactory
{
public static Strategy CreateStrategy(UploadMode mode)
{
switch (mode)
{
case UploadMode.Qiniu:
return new QiNiuStrategy();
case UploadMode.Local:
return new LocalStrategy();
default:
return new QiNiuStrategy();
}
}
}

第二步:对接服务层

在Interface接口层创建IFileService接口

这里需要安装HttpNuget包,不然没有IFormFile,我下的是Microsoft.AspNetCore.Http/2.2.2

public interface IFileService
{
Task<string> Upload(List<IFormFile> files, UploadMode mode);
}

在Service层创建FileService类实现上面的接口

public class FileService:IFileService
{
public async Task<string> Upload(List<IFormFile> files, UploadMode mode)
{
FileContext fileContext = new FileContext(FileFactory.CreateStrategy(mode), files);
return await fileContext.ContextInterface();
}
}

上述通过上下文调用具体的策略,通过工厂去创建具体的类,工厂更据传入的枚举作为参数(构造函数传参),通过上下文的ContextInterface就可以完成上传的逻辑了。

策略+工厂的好处就是,以后需要修改上传文件,只需要对策略进行更改和补充即可。意思就是新增一个上传策略,只需要创建一个策略类,然后去工厂类new一个就行了,不需要动Service层的东西。

本地上传功能实现

在本地策略类中实现上传方法

注意var filePath = $"{AppContext.BaseDirectory}/wwwroot";是将文件保存在bin目录下的wwwroot目录了

public class LocalStrategy:Strategy
{
public override async Task<string> Upload(List<IFormFile> formFiles)
{
var res = await Task.Run(() =>
{
//存放多个文件路径
List<string> result = new List<string>();
foreach (var formFile in formFiles)
{
if (formFile.Length > 0)
{
var filePath = $"{AppContext.BaseDirectory}/wwwroot";
var fileName = $"/{DateTime.Now:yyyyMMddHHmmssffff}{formFile.FileName}";
if (!Directory.Exists(filePath))
{
Directory.CreateDirectory(filePath);
}
using (var stream = System.IO.File.Create(filePath + fileName))
{
formFile.CopyTo(stream);
}
result.Add(fileName);
}
}
return string.Join(",", result);
});
return res;
}
}

七牛云上传功能实现

注册七牛云:https://www.qiniu.com/

从个人中心获取秘钥信息,安装SDK,编写上传逻辑

在Service层安装QiniuNuget包

ak、sk为七牛云的秘钥,在个人中心查看

public class QiNiuStrategy : Strategy
{
public override async Task<string> Upload(List<IFormFile> formFiles)
{
//先上传到本地,才能上传到七牛云,上传完成后本地的文件可删除
var res = await Task.Run(() =>
{
Mac mac = new Mac("ak", "sk");
List<string> result = new List<string>();
foreach (var formFile in formFiles)
{
if (formFile.Length > 0)
{
var filePath_temp = $"{AppContext.BaseDirectory}/Images_temp";
var fileName = $"{DateTime.Now:yyyyMMddHHmmssffff}{formFile.FileName}";
if (!Directory.Exists(filePath_temp))
{
Directory.CreateDirectory(filePath_temp);
} using (var stream = System.IO.File.Create($"{filePath_temp}/{fileName}"))
{
formFile.CopyTo(stream);
} // 上传文件名
string key = fileName;
// 本地文件路径
string filePath = $"{filePath_temp}/{fileName}";
// 存储空间名
string Bucket = "pl-static";
// 设置上传策略
PutPolicy putPolicy = new PutPolicy();
// 设置要上传的目标空间
putPolicy.Scope = Bucket;
// 上传策略的过期时间(单位:秒)
//putPolicy.SetExpires(3600);
// 文件上传完毕后,在多少天后自动被删除
//putPolicy.DeleteAfterDays = 1;
// 生成上传token
string token = Auth.CreateUploadToken(mac, putPolicy.ToJsonString());
Config config = new Config();
// 设置上传区域
config.Zone = Zone.ZONE_CN_East;
// 设置 http 或者 https 上传
config.UseHttps = true;
config.UseCdnDomains = true;
config.ChunkSize = ChunkUnit.U512K;
// 表单上传
FormUploader target = new FormUploader(config);
HttpResult httpResult = target.UploadFile(filePath, key, token, null);
result.Add(fileName);
//删除备份文件夹
Directory.Delete(filePath_temp, true);
}
} return string.Join(",", result);
});
return res;
}
}

Controller的实现

mode为1则会执行本地上传的逻辑代码,为2则会执行七牛云上传的服务代码。

[Route("api/[controller]/[action]")]
[ApiController]
public class FileController : ControllerBase
{
private readonly IFileService _fileService;
public FileController(IFileService fileService)
{
_fileService = fileService;
}
/// <summary>
/// 上传文件
/// </summary>
/// <param name="file">文件对象</param>
/// <param name="mode">上传方式:本地或者七牛云</param>
/// <returns></returns>
[HttpPost]
public async Task<ApiResult> UploadFile(List<IFormFile> file, UploadMode mode)
{
return ResultHelper.Success(await _fileService.Upload(file, mode));
}
}

测试

返回的图片路径可以根据自己的需求进行更改。

去bin目录查看图片是否上传成功

总结

上述内容就是对于文件上传服务的设计,有其他文件上传需求,比如分片断点上传、上传到其他的服务商,只需要新增策略,完成逻辑代码即可,还是很方便的一种文件上传设计。

.NET 文件上传服务设计的更多相关文章

  1. 构建基于阿里云OSS文件上传服务

    转载请注明来源:http://blog.csdn.net/loongshawn/article/details/50710132 <构建基于阿里云OSS文件上传服务> <构建基于OS ...

  2. Atitit  文件上传  架构设计 实现机制 解决方案  实践java php c#.net js javascript  c++ python

    Atitit  文件上传  架构设计 实现机制 解决方案  实践java php c#.net js javascript  c++ python 1. 上传的几点要求2 1.1. 本地预览2 1.2 ...

  3. Java FtpClient 实现文件上传服务

    一.Ubuntu 安装 Vsftpd 服务 1.安装 sudo apt-get install vsftpd 2.添加用户(uftp) sudo useradd -d /home/uftp -s /b ...

  4. 在 .NET Core项目中使用UEditor图片、文件上传服务

    在.NET Framework中使用UEditor时,只需要将UEditor提供的后端服务,部署为一个子程序,即可直接使用文件上传相关的服务,但是UEditor官方并未提供.Net Core的项目,并 ...

  5. nodejs 文件上传服务端实现

    前段时间在做个人项目的时候,用到了nodejs服务端上传文件,现在回头把这个小结一下,作为记录. 本人上传文件时是基于express的multiparty,当然也可以使用connect-multipa ...

  6. 记一次阿里云oss文件上传服务假死

    引言 记得以前刚开始学习web项目的时候,经常涉及到需要上传图片啥的,那时候都是把图片上传到当前项目文件夹下面,每次项目一重启图片就丢了.虽然可以通过修改/tomcat/conf/server.xml ...

  7. HTML+JS+CSS实现图片文件上传界面设计的例子

    在Java Web应用程序设计中文件上传功能的实现是一项非常重要的工作,本文中的例子程序实现了文件上传功能的界面设计.在Java Web应用程序设计中涉及到上传图片文件功能时,往往都需要对图片文件进行 ...

  8. PHP 文件上传服务端及客户端配置参数说明

    文件上传服务器端配置: ·file_uploads = On, 支持HTTP上传 ·upload_tmp_dir = , 临时文件保存的目录 ·upload_max_filesize=2M, 允许上传 ...

  9. koa2实现文件上传服务

    使用方法 方法一: 使用中间介 koa-body 方法二: 自己写个借口去接收数据流并保存 方法三: 使用 koa-body 接受文件,自己写个接口做文件保存或处理等操作 这里简单记录方法三 app. ...

  10. 通过Fastdfs进行文件上传服务(文件和图片的统一处理)

    1.文件上传简单流程分析图: 2.Fastdfs介绍: Fastdfs由两个角色组成: Tracker(集群):调度(帮你找到有空闲的Storage) Storage(集群):文件存储(帮你保存文件或 ...

随机推荐

  1. kubeadm搭建单master多node节点的k8s集群(3)

    一.实验环境准备 K8s集群角色 IP 主机名 安装的组件 配置 控制节点 192.168.1.10 master apiserver.controller-manager.scheduler.etc ...

  2. Maven的概述

    Maven的概述 @ 目录 Maven的概述 2. 依赖 3. Maven 的工作机制 3. 最后:感谢 Java 项目开发过程中,构建指的是使用『原材料生产产品』的过程. 原材料 Java 源代码 ...

  3. SpringMVC学习二(日期参数/数据保存/重定向)

    接受的参数为日期类型 controller进行数据保存 Controller如何进行重定向跳转 1.对于前端页面传来日期类型的数据时如何进行处理,有两种方法 1.1在对应的Controller中插入代 ...

  4. tomcat(2)- tomcat目录结果和配置文件

    目录 1 Tomcat目录结构 2 Tomcat的配置文件 2.1 server.xml配置文件 2.2 server.xml配置文件结构 2.3 WEB应用自动部署 2.4 配置文件各个组件的关联 ...

  5. 案例-java贪吃蛇(附源码)

    创建屏幕 开始游戏的窗口,首先引入窗口,然后在窗口画布上进行添加各类动画. JFrame frame=new JFrame("My SnakeGame"); Jframe 是个类, ...

  6. java程序,如何打印详细报错堆栈信息

    try { System.out.println(1/0); } catch (final Exception e) { log.error("ERROR", "Erro ...

  7. cesium教程7-官方示例翻译-模型要素选择

    源代码示例: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT ...

  8. windows下安装Psycopg2,用于python连接postgresql

    1.首先,下载Windows版的Psycopg2.进入https://pypi.python.org/pypi/psycopg2/ ,在下载文件列表中选择psycopg2-2.7.4-cp33-cp3 ...

  9. 我的书《Unity3D动作游戏开发实战》出版了

    首先感谢帮助和参与前期检阅的朋友们.本书是我经验积累的提炼,书中既有干货分享也有对基础内容的详解补充. 同时由于是第一次撰写书籍,许多地方仍有不足还请读者朋友们见谅. 在京东或当当等都可以购买到本书: ...

  10. JDK源码阅读-------自学笔记(十九)(容器概念初探和泛型概念)

    简介 数组存在的优势和劣质 优势 数组是线性序列,从效率和类型检查的角度讲,数组是最好的 劣势 不灵活,数组的大小是预先定义好的,不会随意改变 引入容器 容器这个概念就是装东西的介质,可以理解为能装东 ...