循序渐进学.Net Core Web Api开发系列【5】:文件上传

2021-04-01 17:27

阅读:666

YPE html>

标签:tle   doc   ddc   ado   bin   利用   lib   ati   formdata   

系列目录

循序渐进学.Net Core Web Api开发系列目录

 本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi

 

一、概述

本篇介绍通过.NET core WebApi实现文件上传。

 

二、Controller端代码

直接上代码:

    [Route("api/files")]   
    [Produces("application/json")]
    public class FileController : Controller
    {
        private readonly IHostingEnvironment _hostingEnvironment;

        public FileController(IHostingEnvironment hostingEnvironment)
        {
            _hostingEnvironment = hostingEnvironment;
        }

        [HttpPost("iform")]
        public ResultObject UploadIForm(List files)
        {          
            List filenames = new Liststring>();  foreach (var file in files)
            {
                var fileName = file.FileName;
                Console.WriteLine(fileName);

                fileName = $"/UploadFile/{fileName}";
                filenames.Add(fileName);

                fileName = _hostingEnvironment.WebRootPath + fileName;

                using (FileStream fs = System.IO.File.Create(fileName))
                {
                    file.CopyTo(fs);
                    fs.Flush();
                }
            }

            return new ResultObject
            {
                state = "Success",
                resultObject = filenames
            };
        }    

为了同时返回上传的文件名和操作状态,我们定义了一个ResultObject的类来返回信息。

    public class ResultObject
    {
        public String state { get; set; }
        public Object resultObject { get; set; }
    }

返回上传的文件名称列表的目的是因为后台可能会给文件重新命名,以避免冲突,新的文件名称需要让前台知道。

后台的files是通过传入的参数获得的,还有其他两种方法可以获取到文件,效果一样:

       [HttpPost]
        public ResultObject UploadAjax()
        { 
            var files = Request.Form.Files;
            ...
         }

或:

       public ResultObject UploadForm(IFormCollection form)
        {    
            var files = form.Files;
            ...
       }

除了获取到files的方式不同,其他操作完全一致。

 

三、前端代码

"utf-8" />
    
"myform" method="post" action="/api/files/iform" enctype="multipart/form-data"> "file" id="files" name="files" multiple />

"formupload" type="button" value="Form Data Upload" onclick="AjaxFormDataUploadfile();" />

两个注意点:

1、form要提供enctype="multipart/form-data" 属性

2、如果要上传多个文件,文件表单需要提供multiple属性

这里我们通过FormData对象的append操作来构建提交的数据,根据我上一篇博客提到的,这里提交数据还有其他两个办法:

        function formuploadfile() {
            $("#myform").ajaxSubmit();
        }

或者:

        function Ajaxuploadfile() {
            var formdata = new FormData(document.getElementById("myform"));

            $.ajax({
                type: "POST",
                url: "/api/files/iform",
                contentType: false,
                processData: false,
                data: formdata,
                success: function (result) {
                    alert("success");
                    $.each(result.resultObject, function (i, filename) {
                        alert(filename);
                    });
                },
                error: function () {
                    alert("上传文件出现错误!");
                }
            });
        }

具体选择哪种方式,要看前端的需求,个人认为 var formdata = new FormData(document.getElementById("myform")); 比较方便。

 

四、上传大文件

上传大文件和上传小文件代码是一样的,关键是上传大文件时间太长,需要前端提供进度报告,不然用户体验太差。

解决的方案是利用ajax的HXR对象。


"utf-8" />
    
"myform" method="post" action="/api/files/iform" enctype="multipart/form-data">

表单多个上传文件:


"file" id="files" name="files" multiple />

"formuploadprogress" type="button" value="Ajax Upload Progress" onclick="AjaxuploadfileWithprogress();" />

"parent">
"son">

 此时,可以看到上传进度条了,可以选择一个大文件测试一下。或者把浏览器的传输速度调低也可以进行调试。

技术分享图片

 

五、为Swagger提供文件上传调试功能支持

目前swagger是不支持List类型的,为了方便调试,我们为swagger提供该类型的支撑。

新增类:

public class SwaggerFileUploadListFilter : IOperationFilter
    {       
        public void Apply(Operation operation, OperationFilterContext context)
        {
            if (!context.ApiDescription.HttpMethod.Equals("POST", StringComparison.OrdinalIgnoreCase) &&
                !context.ApiDescription.HttpMethod.Equals("PUT", StringComparison.OrdinalIgnoreCase))
            {
                return;
            }

            var fileParameters = context.ApiDescription.ActionDescriptor.Parameters.Where(n => n.ParameterType == typeof(List)).ToList();

            if (fileParameters.Count 0)
            {
                return;
            }

            operation.Consumes.Add("multipart/form-data");
foreach (var fileParameter in fileParameters) { var parameter = operation.Parameters.Single(n => n.Name == fileParameter.Name); operation.Parameters.Remove(parameter); NonBodyParameter p = new NonBodyParameter { Name = parameter.Name, In = "formData", Description = parameter.Description, Required = parameter.Required, Type = "file" }; operation.Parameters.Add(p); } } }

在Startup类的ConfigureServices方法里注册该过滤器:

       public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
            services.AddCors();                      

            services.AddSwaggerGen(option =>
            {
                option.SwaggerDoc("v1", new Info
                {
                    Version = "v1",
                    Title = "SaleService接口文档",
                    Description = "RESTful API for SaleService.",
                    TermsOfService = "None",
                    Contact = new Contact { Name = "seabluescn", Email = "seabluescn@163.com", Url = "" }
                });
               
                option.OperationFilter();

                //Set the comments path for the swagger json and ui.
                var basePath = PlatformServices.Default.Application.ApplicationBasePath;
                var xmlPath = Path.Combine(basePath, "SaleService.xml");
                option.IncludeXmlComments(xmlPath);
            });
        }

此时可以通过swagger选择文件了

技术分享图片

但有个缺点是只能上传一个文件,如何实现可以选择多个文件还不会搞。

 

循序渐进学.Net Core Web Api开发系列【5】:文件上传

标签:tle   doc   ddc   ado   bin   利用   lib   ati   formdata   

原文地址:https://www.cnblogs.com/seabluescn/p/9229760.html


评论


亲,登录后才可以留言!