首页 > 其他分享 >.NET 文件上传服务设计

.NET 文件上传服务设计

时间:2023-06-15 16:14:37浏览次数:45  
标签:文件 filePath List formFiles new NET 上传 public

.NET文件上传服务设计

前言

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

项目结构如下:

image

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

枚举

在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));
    }
}

测试

image

image

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

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

image

总结

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

标签:文件,filePath,List,formFiles,new,NET,上传,public
From: https://www.cnblogs.com/ZYPLJ/p/17483162.html

相关文章

  • 上传自己java项目到maven中央仓库pom
    前提首先的你项目需要在Gitee或者Github上有仓库我这里以Gitee是的yhchat-sdk-core仓库为例开始在sonatype上创建问题访问sonatype注册并登录创建一个问题概要填仓库名称描述随意写写GroupId填写自己的域名,如果没有域名的话,可以自行百度使用Gitee、Github的域名需......
  • springboot文件上传
    前言需要实现文件上传功能需要MultipartResolver接口的实现类的实例,这样才可以实现文件上传而MultipartResolver有两个实现类:StandardServletMultipartResolver:springboot中以自动配置完成,直接使用即可CommonsMultipartResolver:springmvc中使用的是CommonsMultipartReso......
  • c#.net WebUploader 分块上传
    ​ 以ASP.NETCoreWebAPI 作后端 API ,用 Vue 构建前端页面,用 Axios 从前端访问后端 API,包括文件的上传和下载。 准备文件上传的API #region 文件上传  可以带参数        [HttpPost("upload")]        publicJsonResultuploadProject(I......
  • 利用 inotifywait 实现自动增量文件拷贝
    #!/bin/bashsrc=/www/wwwroot/site0/images/dest=/www/wwwroot/site1/images/tool=/user/bin/mytoolinotifywait-mrq--format'%w%f'-ecreate$src|whilereadfiledosleep1#从create到写好,有一个过程,等一下更安全rpath=$dest/${file:2......
  • python unitest 文件结构
    unittest框架的文件结构可以按照以下方式组织:1.导入所需的模块和类:在测试文件的开头,需要导入unittest模块以及待测试的模块或类。2.定义测试类:使用class关键字定义一个测试类,类名通常以"Test"开头,并继承unittest.TestCase类。3.定义测试方法:在测试类中,可以定义多个......
  • 6、华为设备telnet/ssh远程访问设置(与华三类似)
    一、telnet远程访问协议配置1、telnet远程控制拓扑图实现功能:AR1路由器模拟访问主机,AR2路由器通过配置telnet远程控制协议,实现远程控制。 2、项目操作步骤AR1基本配置(客户端)<Huawei>system-view[Huawei]sysnameAR1[AR1]interfaceGigabitEthernet0/0/0[AR1-GigabitEt......
  • React图片上传组件设计
    本文讨论React图片上传组件的正确设计思路。程序员对React图片上传组件主要有如下几点关心:界面方面:自动提供图片预览功能,能删除错传的图,传图数量限制等。编程方面:上传时机是否可以外部编程控制,如果是(1)即拍即传,则不能控制也无妨,如果是(2)批量上传,则外部需要有能力控制上传时机;每一张图......
  • python发送文件
      发送端importsocketimportosimporttimefilename=input('pleaseenterthefilenameyouwanttosend:\n')filesize=str(os.path.getsize(filename))fname1,fname2=os.path.split(filename)client_addr=('127.0.0.1',9999)f=op......
  • asp.net WebUploader 分块上传
    ​IE的自带下载功能中没有断点续传功能,要实现断点续传功能,需要用到HTTP协议中鲜为人知的几个响应头和请求头。 一. 两个必要响应头Accept-Ranges、ETag        客户端每次提交下载请求时,服务端都要添加这两个响应头,以保证客户端和服务端将此下载识别为可以断点续传......
  • Kubernetes Pod 驱逐详解
    参考网址1参考网址2QoS等级为Guaranteed的Pod会在QoS等级为Burstable的Pod之前被驱逐吗?在Kubernetes中,Pod使用的资源最重要的是CPU、内存和磁盘IO,这些资源可以被分为可压缩资源(CPU)和不可压缩资源(内存,磁盘IO)。可压缩资源不可能导致Pod被驱逐,因为当Pod的......