public class FileAPIController : BaseController
    {
        private readonly string prefix = "thumb_";
        private readonly Token token;
        private readonly ServiceImpl.Config.AppConfig config;
        /// <summary>
        /// 上传图片
        /// </summary>
        /// <param name="token"></param>
        /// <param name="config"></param>
        public FileAPIController(Token token, ServiceImpl.Config.AppConfig config)
        {
            this.config = config;
            this.token = token;
            if (token == null)
            {
                throw new ApiException(HttpStatusCode.Unauthorized, "用户登录已过期!");
            }
        }

#region 上传文件

/// <summary>
        /// 上传文件
        /// </summary>
        /// <param name="subpath">文件子目录</param>
        /// <param name="thumbnail">缩略图大小,格式:width*height,为空不生成缩略图</param>
        /// <returns></returns>
        [HttpPost]
        [Route("v1/file/{subpath}")]
        public async Task<IEnumerable<string>> Upload(string subpath = null, string thumbnail = null)
        {
            if (token == null || token.EntCode == null)
            {
                throw new ApiException(HttpStatusCode.Unauthorized, "用户登录已过期!");
            }
            if (!Request.Content.IsMimeMultipartContent())
            {
                throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
            }

List<string> files = new List<string>();
            try
            {
                MultipartMemoryStreamProvider provider = new MultipartMemoryStreamProvider();
                await Request.Content.ReadAsMultipartAsync(provider);

#region 文件目录

string root = GetRoot(subpath, string.Empty);
                if (!Directory.Exists(root))
                {
                    Directory.CreateDirectory(root);
                }

#endregion

foreach (HttpContent file in provider.Contents)
                {
                    string filename = file.Headers.ContentDisposition.FileName.Trim('\"');
                    byte[] buffer = await file.ReadAsByteArrayAsync();

string savename = Guid.NewGuid().ToString("N");

string uploadFileName = $"{savename}{Path.GetExtension(filename)}";

string filePath = $"{root}\\{uploadFileName}";

File.WriteAllBytes(filePath, buffer);

files.Add($"{(string.IsNullOrWhiteSpace(subpath) ? "" : $"{subpath}\\")}{uploadFileName}");

#region 是否生成缩略图

if (!string.IsNullOrWhiteSpace(thumbnail) && new Regex(@"\d+\*\d+").IsMatch(thumbnail))
                    {
                        int width = int.Parse(thumbnail.Split('*')[0]);
                        int height = int.Parse(thumbnail.Split('*')[1]);
                        if (width < 1)
                        {
                            width = 100;
                        }

if (height < 1)
                        {
                            height = 100;
                        }

string thumbnailPath = $"{root}\\{prefix}{savename}.png";
                        MakeThumbnail(filePath, thumbnailPath, width, height);
                    }

#endregion
                }
            }
            catch (Exception ex)
            {
                log.Error($"上传文件出错", ex);
            }

return files;
        }

#endregion

#region 上传文件

/// <summary>
        /// 上传文件
        /// </summary>
        /// <param name="subpath">子目录</param>
        /// <param name="filename">文件名称</param>
        /// <param name="thumbnail">true=输出缩略图,false=输出原图</param>
        /// <returns></returns>
        [HttpGet]
        [Route("v1/file/{subpath}/{filename}")]
        public async Task<HttpResponseMessage> Get(string subpath, string filename, bool thumbnail = true)
        {
            if (string.IsNullOrWhiteSpace(filename))
            {
                throw new ApiException(HttpStatusCode.BadRequest, "无效参数");
            }

#region 文件名解密

string name = filename.Substring(0, filename.LastIndexOf('.'));
            if (string.IsNullOrWhiteSpace(name))
            {
                throw new ApiException(HttpStatusCode.BadRequest, "无效参数");
            }

#endregion

try
            {
                string path = GetRoot(subpath, thumbnail ? $"{prefix}{name}.png" : filename);
                if (File.Exists(path))
                {
                    FileStream stream = new FileStream(path, FileMode.Open);

HttpResponseMessage resp = new HttpResponseMessage(HttpStatusCode.OK)
                    {
                        Content = new StreamContent(stream)
                    };
                    resp.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
                    {
                        FileName = Path.GetFileName(path)
                    };
                    string contentType = MimeMapping.GetMimeMapping(path);
                    resp.Content.Headers.ContentType = new MediaTypeHeaderValue(contentType);
                    resp.Content.Headers.ContentLength = stream.Length;

return await Task.FromResult(resp);
                }
            }
            catch (Exception ex)
            {
                if (log != null)
                {
                    log.Error($"下载文件出错:{token}", ex);
                }
            }
            return new HttpResponseMessage(HttpStatusCode.NoContent);
        }

#endregion

#region 删除文件

/// <summary>
        /// 删除文件
        /// </summary>
        /// <param name="subpath">子目录</param>
        /// <param name="filename">文件名称</param>
        /// <returns></returns>
        [HttpDelete]
        [Route("v1/file/{subpath}/{filename}")]
        public bool Delete(string subpath, string filename)
        {
            if (token == null || token.EntCode == null)
            {
                throw new ApiException(HttpStatusCode.Unauthorized, "用户登录已过期!");
            }
            if (string.IsNullOrWhiteSpace(filename))
            {
                throw new ApiException(HttpStatusCode.BadRequest, "无效参数");
            }
            bool result = true;
            try
            {
                string path = GetRoot(subpath, filename);
                if (File.Exists(path))
                {
                    File.Delete(path);
                }
            }
            catch (Exception ex)
            {
                log.Error($"删除文件出错:{subpath}/{filename}", ex);
                result = false;
            }
            try
            {
                string name = filename.Substring(0, filename.LastIndexOf('.'));
                string thumbnailPath = GetRoot(subpath, $"{prefix}{name}.png");
                if (File.Exists(thumbnailPath))
                {
                    File.Delete(thumbnailPath);
                }
            }
            catch (Exception ex)
            {
                log.Error($"删除缩略图出错:{subpath}/{filename}", ex);
            }
            return result;
        }

#endregion

#region 文件目录

/// <summary>
        /// 文件目录
        /// </summary>
        /// <param name="subpath">文件子目录</param>
        /// <param name="filename">文件名称</param>
        /// <returns></returns>
        private string GetRoot(string subpath, string filename)
        {
            #region 文件目录

string appName = AppConfig.Default.AppName;
            string fileDir = config.UploadRoot;
            if (string.IsNullOrWhiteSpace(fileDir) || string.IsNullOrWhiteSpace(Path.GetDirectoryName(fileDir)))
            {
                fileDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Upload");
            }
            return Path.Combine(fileDir, appName, subpath, filename);

#endregion
        }

#endregion

#region 生成缩略图

/// <summary>
        /// 生成缩略图
        /// </summary>
        /// <param name="originalImagePath">源图路径(物理路径)</param>
        /// <param name="thumbnailPath">缩略图路径(物理路径)</param>
        /// <param name="width">缩略图宽度</param>
        /// <param name="height">缩略图高度</param>   
        private void MakeThumbnail(string originalImagePath, string thumbnailPath, int width, int height)
        {
            Image originalImage = Image.FromFile(originalImagePath);

int towidth = width;
            int toheight = height;

int x = 0;
            int y = 0;
            int ow = originalImage.Width;
            int oh = originalImage.Height;

if (originalImage.Width / (double)originalImage.Height > towidth / (double)toheight)
            {
                ow = originalImage.Width;
                oh = originalImage.Width * height / towidth;
                x = 0;
                y = (originalImage.Height - oh) / 2;
            }
            else
            {
                oh = originalImage.Height;
                ow = originalImage.Height * towidth / toheight;
                y = 0;
                x = (originalImage.Width - ow) / 2;
            }

Image bitmap = new System.Drawing.Bitmap(towidth, toheight);
            Graphics g = System.Drawing.Graphics.FromImage(bitmap);
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            g.Clear(Color.Transparent);
            g.DrawImage(originalImage, new Rectangle(0, 0, towidth, toheight), new Rectangle(x, y, ow, oh), GraphicsUnit.Pixel);
            try
            {
                bitmap.Save(thumbnailPath, System.Drawing.Imaging.ImageFormat.Png);
            }
            catch (System.Exception e)
            {
                throw e;
            }
            finally
            {
                originalImage.Dispose();
                bitmap.Dispose();
                g.Dispose();
            }
        }

#endregion
    }

c# webapi上传、读取、删除图片的更多相关文章

  1. vue实现图片的上传和删除

    目录 1 UI库使用ElementUI 2 后端使用Express + formidable模块 1 UI库使用ElementUI 安装ElementUI $ npm install --save-d ...

  2. Owin WebAPI上传文件

    Owin是微软出了几年的东东了,一直没时间学习.大概了解了下,是一个脱离IIS环境,快速搭建WebAPI服务的东西. 刚好想尝试下尽量脱离IIS创建简单快捷配置的项目,就是用了Nginx+Owin的模 ...

  3. dropzonejs中文翻译手册 DropzoneJS是一个提供文件拖拽上传并且提供图片预览的开源类库.

    http://wxb.github.io/dropzonejs.com.zh-CN/dropzonezh-CN/ 由于项目需要,完成一个web的图片拖拽上传,也就顺便学习和了解了一下前端的比较新的技术 ...

  4. 使用C#WebClient类访问(上传/下载/删除/列出文件目录)由IIS搭建的http文件服务器

    前言 为什么要写这边博文呢?其实,就是使用C#WebClient类访问由IIS搭建的http文件服务器的问题花了我足足两天的时间,因此,有必要写下自己所学到的,同时,也能让广大的博友学习学习一下. 本 ...

  5. AngularJS之WebAPi上传

    AngularJS之WebAPi上传(十)   前言 前面一系列我们纯粹是讲AngularJS,在讲一门知识时我们应该结合之前所学综合起来来做一个小的例子,前面我们讲了在MVC中上传文件的例子,在本节 ...

  6. DropzoneJS是一个提供文件拖拽上传并且提供图片预览的开源类库.

    DropzoneJS是一个提供文件拖拽上传并且提供图片预览的开源类库. 它是轻量级的,不依赖任何其他类库(如JQuery)并且高度可定制. 试试看! 将文件拖至此处或点击上传.(这仅仅是 dropzo ...

  7. 使用C#WebClient类访问(上传/下载/删除/列出文件目录)

    在使用WebClient类之前,必须先引用System.Net命名空间,文件下载.上传与删除的都是使用异步编程,也可以使用同步编程, 这里以异步编程为例: 1)文件下载: static void Ma ...

  8. bootstrap-fileinput上传文件的插件使用总结----编辑已成功上传过的图片

    http://plugins.krajee.com/file-plugin-methods-demo 具体操作 http://plugins.krajee.com/file-preview-manag ...

  9. SpringMVC上传文件(图片)并保存到本地

    SpringMVC上传文件(图片)并保存到本地 小记一波~ 基本的MVC配置就不展示了,这里给出核心代码 在spring-mvc的配置文件中写入如下配置 <bean id="multi ...

  10. 图片上传5-多个图片上传,独立项目Demo和源码

    图片上传,一次性可以上传多个图片,每个图片可以有名字.URL.排序.备注等字段.这是区别于使用百度WebUploader等多图上传工具的地方. 项目相关图片 Jar包管理:Maven用到的框架:Spr ...

随机推荐

  1. CodeForces - 1013B And 与运算暴力

    题目链接: https://vjudge.net/problem/1735275/origin 基本思路: 本题思路比较简单,首先,我们知道 a & x = b, b & x = b; ...

  2. django——form组件

    1.html表单概述 Django开发的是动态Web服务,而非单纯提供静态页面.动态服务的本质在于和用户进行互动,接收用户的输入,根据输入的不同,返回不同的内容给用户.返回数据是我们服务器后端做的,而 ...

  3. 求n到m之间素数的个数

    Description 求n到m之间素数的个数 Input 多组测试数据,每组先输入一个整数t,表示组数,然后每组输入2个正整数n和m,(1 <= n <= m <= 10000) ...

  4. PHP定界符<<<EOF

    PHP定界符<<<EOF 一.为什么需要使用定界符: 因为在编程过程中难免会遇到用echo来输出大段的html和javascript脚本的情况, 如果用传统的输出方法 ——按字符串输 ...

  5. __x__(3)0905第二天__W3C标准集合

    World Wide Web Consortium 万维网联盟(外语缩写:W3C)标准不是某一个标准,而是一系列标准的集合. 创建于 1994 年,是 Web 技术领域最具权威和影响力的国际中立性技术 ...

  6. mobile_1 物理像素

    1 物理像素 需求: border: 1px solid red; 在移动端 dpr 为 2 的屏幕上,实际上是 2 物理像素.    如何实现 1 物理像素? 首先,肯定不能 border: 0.5 ...

  7. JMM(java Memory Model)到底是什么?

    经历过很多面试大部分都会问一句: 你知道Java内存模型么?  然后我就pulapula的说一大堆什么堆呀,栈呀,GC呀什么的,这段时间把JVM虚拟机和多线程编程完整的学习了一遍,发现JMM和堆/栈这 ...

  8. EF Core 相关的千倍性能之差: AutoMapper ProjectTo VS Mapster ProjectToType

    在前两天遇到 .NET Core 中 EF Core 的异步与同步查询的百倍性能之差(详情之前的博文)之后,这两天又遇到了 AutoMapper ProjectTo<T> 与 Mapste ...

  9. Python全栈-magedu-2018-笔记9

    第三章 - Python 内置数据结构 封装和解构 封装 将多个值使用逗号分割,组合在一起 本质上,返回一个元组,只是省掉了小括号 python特有语法,被很多语言学习和借鉴    t1 = (1,2 ...

  10. kettle 通用的数据库迁移流程

    需求: 1.你是否遇到了需要将mysql数据库中的所有表与数据迁移到Oracle. 2.你是否还在使用kettle重复的画着:表输入-表输出.创建表,而烦恼. 下面为你实现了一套通用的数据库迁移流程. ...