基于.NetCore开发博客项目 StarBlog - (25) 图片接口与文件上传

1前言

上传文件的接口设计有两种风格,一种是整个项目只设置一个接口用来上传,然后其他需要用到文件的地方,都只存一个引用ID;另一种是每个需要文件的地方单独管理各自的文件。这俩各有优劣吧,本项目中选择的是后者的风格,文章图片和照片模块又要能CRUD又要批量导入,还是各自管理文件比较好。

2图片接口

说会正题,先介绍一下图片相关接口。

图片列表

首先CRUD是肯定有的,图片列表的分页查看也是有的,不过因为筛选功能没有做,所以就不定义一个ViewModel作为参数了。

控制器代码 StarBlog.Web/Apis/Blog/PhotoController.cs

[HttpGet]
public ApiResponsePaged<Photo> GetList(int page = 1, int pageSize = 10) {var paged = _photoService.GetPagedList(page, pageSize);return new ApiResponsePaged<Photo> {Pagination = paged.ToPaginationMetadata(),Data = paged.ToList()};
}

跟博客前台公用一套图片列表逻辑,所以这部分抽出来放在service,代码如下

StarBlog.Web/Services/PhotoService.cs

public IPagedList<Photo> GetPagedList(int page = 1, int pageSize = 10) {return _photoRepo.Select.OrderByDescending(a => a.CreateTime).ToList().ToPagedList(page, pageSize);
}

单个图片

获取单个图片,跟获取文章的差不多,传入ID,找不到就返回404,找到就返回图片对象

[HttpGet("{id}")]
public ApiResponse<Photo> Get(string id) {var photo = _photoService.GetById(id);return photo == null? ApiResponse.NotFound($"图片 {id} 不存在"): new ApiResponse<Photo> {Data = photo};
}

图片缩略图

在本系列第20篇中,本项目已经实现了图片显示的优化,详见:基于.NetCore开发博客项目 StarBlog - (20) 图片显示优化

除了 ImageSharp 组件提供的图片缩略图功能外,我这里还写了另一个生成缩略图的方法,这个方法有俩特点

  • 直接在内存中生成返回,不会写入缓存文件

  • 生成的是Progressive JPEG格式,目前 ImageSharp 是不支持的,可以优化前端的加载速度

控制器代码

[HttpGet("{id}/Thumb")]
public async Task<IActionResult> GetThumb(string id, [FromQuery] int width = 300) {var data = await _photoService.GetThumb(id, width);return new FileContentResult(data, "image/jpeg");
}

service代码

/// <summary>
/// 生成Progressive JPEG缩略图 (使用 MagickImage)
/// </summary>
/// <param name="width">设置为0则不调整大小</param>
public async Task<byte[]> GetThumb(string id, int width = 0) {var photo = await _photoRepo.Where(a => a.Id == id).FirstAsync();using (var image = new MagickImage(GetPhotoFilePath(photo))) {image.Format = MagickFormat.Pjpeg;if (width != 0) {image.Resize(width, 0);}return image.ToByteArray();}
}

这个 MagickImage 是用 C++ 写的,在不同平台上引用不同 native 库,需要在 csproj 里面写上配置,这样发布的时候才会带上对应的依赖库,而且似乎在 CentOS 系统上会有坑…

<!--  复制 Magick 库  -->
<PropertyGroup><MagickCopyNativeWindows>true</MagickCopyNativeWindows><MagickCopyNativeLinux>true</MagickCopyNativeLinux><MagickCopyNativeMacOS>true</MagickCopyNativeMacOS>
</PropertyGroup>

其他接口

还有一些接口,跟之前介绍的大同小异,再重复一次也意义不大,读者有需要的话可以自行查看源码。

  • 删除图片

  • 设置和取消推荐

  • 重建图片库数据(更新每个图片的尺寸等数据,一般情况下不需要用到)

  • 批量导入(本系列的第9篇已经介绍过)详见:基于.NetCore开发博客项目 StarBlog - (9) 图片批量导入

3图片文件上传

这个同时也是图片的添加接口

先定义DTO

public class PhotoCreationDto {/// <summary>/// 作品标题/// </summary>[Required(ErrorMessage = "作品标题不能为空")]public string Title { get; set; }/// <summary>/// 拍摄地点/// </summary>[Required(ErrorMessage = "拍摄地点不能为空")]public string Location { get; set; }
}

控制器代码

[Authorize]
[HttpPost]
public ApiResponse<Photo> Add([FromForm] PhotoCreationDto dto, IFormFile file) {var photo = _photoService.Add(dto, file);return !ModelState.IsValid? ApiResponse.BadRequest(ModelState): new ApiResponse<Photo>(photo);
}

因为上传的同时还要附带一些数据,需要使用 FormData 传参,所以这里使用 [FromForm] 特性标记这个 dto 参数

IFormFile 类型的参数可以拿到上传上来的文件

下面是service代码

public Photo Add(PhotoCreationDto dto, IFormFile photoFile) {var photoId = GuidUtils.GuidTo16String();var photo = new Photo {Id = photoId,Title = dto.Title,CreateTime = DateTime.Now,Location = dto.Location,FilePath = Path.Combine("photography", $"{photoId}.jpg")};var savePath = Path.Combine(_environment.WebRootPath, "media", photo.FilePath);// 如果超出最大允许的大小,则按比例缩小const int maxWidth = 2000;const int maxHeight = 2000;using (var image = Image.Load(photoFile.OpenReadStream())) {if (image.Width > maxWidth)image.Mutate(a => a.Resize(maxWidth, 0));if (image.Height > maxHeight)image.Mutate(a => a.Resize(0, maxHeight));image.Save(savePath);}// 保存文件using (var fs = new FileStream(savePath, FileMode.Create)) {photoFile.CopyTo(fs);}// 读取图片的尺寸等数据photo = BuildPhotoData(photo);return _photoRepo.Insert(photo);
}

这里对图片做了一些处理,抛开这些细节,其实对上传的文件,最关键的只有几行保存代码

using (var fs = new FileStream("savePath", FileMode.Create)) {photoFile.CopyTo(fs);
}

这样就完成了文件上传接口。

4系列文章

  • 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客?

  • 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目

  • 基于.NetCore开发博客项目 StarBlog - (3) 模型设计

  • 基于.NetCore开发博客项目 StarBlog - (4) markdown博客批量导入

  • 基于.NetCore开发博客项目 StarBlog - (5) 开始搭建Web项目

  • 基于.NetCore开发博客项目 StarBlog - (6) 页面开发之博客文章列表

  • 基于.NetCore开发博客项目 StarBlog - (7) 页面开发之文章详情页面

  • 基于.NetCore开发博客项目 StarBlog - (8) 分类层级结构展示

  • 基于.NetCore开发博客项目 StarBlog - (9) 图片批量导入

  • 基于.NetCore开发博客项目 StarBlog - (10) 图片瀑布流

  • 基于.NetCore开发博客项目 StarBlog - (11) 实现访问统计

  • 基于.NetCore开发博客项目 StarBlog - (12) Razor页面动态编译

  • 基于.NetCore开发博客项目 StarBlog - (13) 加入友情链接功能

  • 基于.NetCore开发博客项目 StarBlog - (14) 实现主题切换功能

  • 基于.NetCore开发博客项目 StarBlog - (15) 生成随机尺寸图片

  • 基于.NetCore开发博客项目 StarBlog - (16) 一些新功能 (监控/统计/配置/初始化)

  • 基于.NetCore开发博客项目 StarBlog - (17) 自动下载文章里的外部图片

  • 基于.NetCore开发博客项目 StarBlog - (18) 实现本地Typora文章打包上传

  • 基于.NetCore开发博客项目 StarBlog - (19) Markdown渲染方案探索

  • 基于.NetCore开发博客项目 StarBlog - (20) 图片显示优化

  • 基于.NetCore开发博客项目 StarBlog - (21) 开始开发RESTFul接口

  • 基于.NetCore开发博客项目 StarBlog - (22) 开发博客文章相关接口

  • 基于.NetCore开发博客项目 StarBlog - (23) 文章列表接口分页、过滤、搜索、排序

  • 基于.NetCore开发博客项目 StarBlog - (24) 统一接口数据返回格式

  • 基于.NetCore开发博客项目 StarBlog - (25) 图片接口与文件上传

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/279977.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pta7-7旅游规划(dijkstra算法)

题目链接&#xff1a;https://pintia.cn/problem-sets/1101307589335527424/problems/1101314114762387456 题意&#xff1a;给n给城市&#xff0c;m条公路&#xff0c;公路是双向的&#xff0c;起点S&#xff0c;终点D&#xff0c;并给出每条公路连接的两个city的编号以及路费…

context:annotation-config vs context:component-scan

<context:annotation-config> 用来注入已经在上下文注册的bean&#xff0c;无论bean是定义在XML中还是被 package scanning。 <context:component-scan>仅scans packages 去注册应用上线文中的Bean。 example&#xff1a; Lets start with a basic setup of three …

Cactiz中文版安装使用

#----------------------------------------------------------# # > 红色字体 -特指煮酒个人所见。加粗则为需要重点注意。 ## > 蓝色加粗 -特指与本文相关人员&#xff0c;包括参与修正的朋友。 ## > 煮酒品茶 -Http://cwtea.blog.51cto.com # #----------…

如何在OS X中打开或关闭鼠标定位器

OS X 10.11 El Capitan includes a new “mouse locator” feature. If you lose your mouse pointer, just shake the mouse or move your finger on the touch pad vigorously, and the mouse pointer will temporarily grow very large so you can see it. OS X 10.11 El Ca…

微软宣布 Win10 设备数突破8亿,距离10亿还远吗?

百度智能云 云生态狂欢季 热门云产品1折起>>> 微软高管 Yusuf Mehdi 昨天在推特发布了一条推文&#xff0c;宣布运行 Windows 10 的设备数已突破 8 亿&#xff0c;比半年前增加了 1 亿。 根据之前的报道&#xff0c;两个月前 Windows 10 的全球市场份额才首次超越 W…

UI自动化web端框架path.py代码

import os,sysBASE_PATH os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))sys.path.insert(0, BASE_PATH)# 配置文件CONF_PATH BASE_PATH os.path.sep conf os.path.sep config.json# 日志的路径WEB_LOG_PATH BASE_PATH os.path.sep lo…

snapchat为什么_我的Snapchat朋友旁边的表情符号是什么意思?

snapchat为什么Next to some of your Snapchat friends, you’ll see little emoji. 在您的某些Snapchat朋友旁边&#xff0c;您会看到小的表情符号。 Each of these emoji has a specific meaning. Let’s look at what they are. 这些表情符号都有特定的含义。 让我们看看它们…

暴力打表之hdu 2089

题目链接&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid2089 有两种方法&#xff1a; 1.数位DP算法 2.暴力打表——真是个好法子&#xff01;&#xff01;&#xff01; 接下来是注意点&#xff1a; 1.一般这种数组中的一个数减去一个数组的另一个数&#xff0c;sum[i…

最全的正则表达式大全

很多不太懂正则的朋友&#xff0c;在遇到需要用正则校验数据时&#xff0c;往往是在网上去找很久&#xff0c;结果找来的还是不很符合要求。所以我最近把开发中常用的一些正则表达式整理了一下&#xff0c;在这里分享一下。给自己留个底&#xff0c;也给朋友们做个参考。 一、校…

关于移动应用APP数据安全的一点见解

2019独角兽企业重金招聘Python工程师标准>>> 项目沟通中过程客户反复在强调&#xff0c;大数据的安全性&#xff0c; 言下之意&#xff0c;用了大数据&#xff0c;就不安全了&#xff0c;就有漏洞了。所以花了些时间&#xff0c;针对大数据的安全设计做了一个总结&a…

2022年底C# 解压zip文件遇到的一个Bug

本文由网友投稿。作者&#xff1a;江湖人士原文标题&#xff1a;2022年底C# 解压zip文件遇到的一个bug原文链接&#xff1a;https://jhrs.com/2022/46060.html最近在排查一个上传功能时&#xff0c;客户端上传的是zip文件&#xff0c;到服务器端后使用C# 解压zip文件的代码将上…

如何关闭mcafee软件_如何摆脱McAfee的通知和捆绑软件

如何关闭mcafee软件McAfee, like most other modern antivirus programs, doesn’t stay out of your way. It installs browser extensions and shows various alert messages you might not want to see. If McAfee came with your PC, you may regularly see messages that …

mfs使用指引

客户端工具集 mfsgetgoal #设定副本数mfssetgoal #获取副本数mfscopygoal # mfsgetsclass mfssetsclass mfscopysclass mfsxchgsclass mfslistsclass mfsgettrashtime #设定回收站时间 mfssettrashtime #设定回收站时间 mfscopytrashtime mfsgeteattr #设置权限 mfsseteattr…

【命名规范】.NET中的枚举类型,要以Enum结尾吗?

“首先要给它一个名字&#xff0c;然后你才能描述它。”图片&#xff1a;北京的晚霞 摄影师&#xff1a;刘先生这个话题源于公司《.NET技术规范》中的一条&#xff1a;【强制】枚举声明应以Enum结尾我对此并不认同&#xff1a;首先&#xff0c;引用一下微软官方文档中&#xff…

Linux中防火墙(一)

一&#xff1a;前言防火墙&#xff0c;其实说白了讲&#xff0c;就是用于实现Linux下访问控制的功能&#xff0c;它分为硬件的或者软件的防火墙两种。无论是在哪个网络中&#xff0c;防火墙工作的地方一定是在网络的边缘。而我们的任务就是需要去定义到底防火墙如何工作&#x…

macos安全性偏好设置_如何更改macOS系统偏好设置的布局

macos安全性偏好设置If you don’t care for the way the System Preferences appear in macOS, you can change them by hiding certain preference panels or by rearranging them alphabetically. 如果您不喜欢系统偏好设置在macOS中的显示方式&#xff0c;则可以通过隐藏某…

机器视觉技术在表面缺陷检测方面的发展趋势

导读&#xff1a;机器视觉技术在表面缺陷检测方面的发展趋势如何&#xff1f;很多人都不了解&#xff0c;据悉&#xff0c;目前工业中应用的机器视觉检测绝大部分执行的是二维检测任务&#xff0c;三维机器视觉检测仍处于理论研究和试验阶段。除此之外&#xff0c;机器视觉检测…

J.U.C之AQS

AQS是J.U.C的核心 AQS(AbstractQueuedSynchronizer)队列同步器&#xff0c;AQS是JDK下提供的一套用于实现基于FIFO等待队列的阻塞锁和相关的同步器的一个同步框架。 同步器面向的是锁的实现者&#xff0c;它简化了锁的实现方式&#xff0c;屏蔽了同步状态管理、线程的排队、等待…

.NET周报【12月第3期 2022-12-23】

由于众所周知的原因&#xff0c;大佬们纷纷加入羊群&#xff0c;笔者也未能幸免&#xff0c;体验下来这绝对不是普通感冒的症状&#xff0c;身体不适&#xff0c;熬了几天&#xff0c;所以本周更新比较晚&#xff1b;另外精力有限&#xff0c;对于国际板块只有链接没有简介&…

亚马逊的vps多少钱一个月_如何查看您在亚马逊上花了多少钱

亚马逊的vps多少钱一个月Have you ever wondered how much you’ve spent at Amazon during your lifetime? Whether you’re feeling curious or just plain brave, there’s an easy way to find out. 您是否想过一生在亚马逊上花了多少钱&#xff1f; 无论您是好奇还是勇敢…