1、@Autowired默认是根据类型(ByType)注入的,@Resource默认是根据名称(ByName)注入的。
2、@Autowired是Spring提供的注解,@Resource是JDK提供的注解
3、当一个接口存在多个实现类,@Autowired和@Resource都是需要指定Bean的名称才能完成注入,@Autowired可通过@Qualifier来只能Bean的名称进行注入,@Resource则可通过name来完成Bean的注入。
View Details在设计模式中有六大设计原则:
单一职责原则:一个类只做一件事
里式替换原则:子类可以扩展父类
依赖倒置原则:面向接口编程
接口隔离原则:高内聚低耦合
迪米特法则:最少知道原则
开闭原则:关闭修改,开放新增
我认为在这六个原则中开闭原则最为重要,开闭原则是可扩展性的重要基石。
第一个原因是需求变化时应该通过新增而不是修改已有代码实现,这样保证了代码稳定性,避免牵一发而动全身。
第二个原因是可以事先定义代码框架,扩展也是根据框架扩展,体现了用抽象构建框架,用实现扩展细节,保证了稳定性也保证了灵活性。
第三个原因是其它五个原则虽然侧重点各有不同,但是都可以包含于开闭原则。
第四个原因是标准二十三种设计模式最终都是在遵循开闭原则。
既然开闭原则如此重要,我们应该怎么在系统设计时遵循开闭原则呢?
View Details
1 2 3 4 5 6 7 |
// 忽略证书验证 if (AppConfig.HisUrl.StartsWith("https")) { ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true; } |
View Details
这个问题很微妙,可能这位同学内心深处,觉得 Redis 是所有应用缓存的标配。
缓存的世界很广阔,对于应用系统来讲,我们经常将缓存划分为本地缓存和分布式缓存。
本地缓存 :应用中的缓存组件,缓存组件和应用在同一进程中,缓存的读写非常快,没有网络开销。但各应用或集群的各节点都需要维护自己的单独缓存,无法共享缓存。
分布式缓存:和应用分离的缓存组件或服务,与本地应用隔离,多个应用可直接共享缓存。
View DetailsNginx 读作 engine x, 是一个免费的、开源的、高性能的 HTTP 和反向代理服务,主要负责负载一些访问量比较大的站点。 Nginx 可以作为一个独立的 Web 服务,也可以用来给 Apache 或是其他的 Web 服务做反向代理。 相比于 Apache,Nginx 可以处理更多的并发连接,而且每个连接的内存占用的非常小。 本教程将会教您如何在 Centos 7 的服务器上安装和管理 Nginx。 开始前的准备 在开始阅读此教程之前,请确保你是以拥有 sudo 权限的用户来登录的服务器,并且服务器中没有 Apache 或是其他服务正在使用 80(HTTP) 和 443(HTTPS) 端口上,防止端口被占用,造成 Nginx 无法正常启动。 在 CentOS 中安装 Nginx 请按照下面的步骤,在 CentOS 中安装 Nginx。 1、 EPEL 仓库中有 Nginx 的安装包。如果你还没有安装过 EPEL,可以通过运行下面的命令来完成安装:
1 |
sudo yum install epel-release |
上面代码的意思是以 sudo 权限运行安装 epel-release,如果你当前登录的用户不是 root,则会提示你输入密码来运行,输入密码时是看不到输入的内容的,所以不用担心,继续输入就行。然后回车继续运行,后面的命令中如果包含 sudo 则都表明是刚提到的意思,不再重复解释。 2、 输入以下命令来安装 Nginx:
1 |
sudo yum install nginx |
如果这是您第一次从 EPEL 仓库中安装软件,yum 可能会提示您导入 EPEL GPG key:
1 2 3 4 5 6 7 |
Retrieving key from file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7 Importing GPG key 0x352C64E5: Userid : "Fedora EPEL (7) <epel@fedoraproject.org>" Fingerprint: 91e9 7d7c 4a5e 96f1 7f3e 888f 6a2f aea2 352c 64e5 Package : epel-release-7-9.noarch (@extras) From : /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7 Is this ok [y/N]: |
类似于上面的内容,遇到这种情况,输入 y,然后 Enter(回车) 即可继续安装。 3、 等到安装完成以后,可以通过以下命令来设置开机启动和运行 Nginx 服务: 设置 Nginx 开机启动:
1 |
sudo systemctl enable nginx |
运行以上命令以后,会输出类似以下的内容,表示创建了一个软连接来关联 Nginx,不用担心,并不是报错了,下一步就可以启动 Nginx 了。
1 |
Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service. |
启动 Nginx:
1 |
sudo systemctl start nginx |
通过运行以下命令,来检查 Nginx 的运行状态:
1 |
sudo systemctl status nginx |
然后会输出类型下面的内容 […]
View DetailsJpa (Java Persistence API) 是 Sun 官方提出的 Java 持久化规范。它为 Java 开发人员提供了一种对象/关联映射工具来管理 Java 应用中的关系数据。它的出现主要是为了简化现有的持久化开发工作和整合 ORM 技术,结束现在 Hibernate,TopLink,JDO 等 ORM 框架各自为营的局面。
值得注意的是,Jpa是在充分吸收了现有 Hibernate,TopLink,JDO 等 ORM 框架的基础上发展而来的,具有易于使用,伸缩性强等优点。从目前的开发社区的反应上看,Jpa 受到了极大的支持和赞扬,其中就包括了 Spring 与 EJB3. 0的开发团队。
View Details1.pom文件导入依赖
1 2 3 4 5 |
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> <version>2.0.4.RELEASE</version> </dependency> |
2.创建webSocket相关配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
package com.example.demo.mainDemo; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.config.annotation.EnableWebSocket; import org.springframework.web.socket.config.annotation.WebSocketConfigurer; import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(myHandler(), "myHandler").setAllowedOrigins("*"); } public WebSocketHandler myHandler() { return new MyHandler(); } } |
3.编写webSocket处理类,类似controller接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package com.example.demo.mainDemo; import com.alibaba.fastjson.JSONObject; import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.handler.TextWebSocketHandler; import java.util.HashMap; import java.util.Map; /** * 相当于controller的处理器 */ public class MyHandler extends TextWebSocketHandler { @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { String payload = message.getPayload(); // Map<String, String> map = JSONObject.parseObject(payload, HashMap.class); // System.out.println("=====接受到的数据"+map); session.sendMessage(new TextMessage("服务器返回收到的信息," + payload)); } } |
4.编写客户端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
package com.example.demo.mainDemo.client; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.websocket.*; @ClientEndpoint public class MyClient { private static Logger logger = LoggerFactory.getLogger(MyClient.class); private Session session; @OnOpen public void open(Session session){ logger.info("Client WebSocket is opening..."); this.session = session; } @OnMessage public void onMessage(String message){ logger.info("Server send message: " + message); } @OnClose public void onClose(){ logger.info("Websocket closed"); } /** * 发送客户端消息到服务端 * @param message 消息内容 */ public void send(String message){ this.session.getAsyncRemote().sendText(message); } } |
5.创建main方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package com.example.demo.mainDemo.client; import javax.websocket.ContainerProvider; import javax.websocket.WebSocketContainer; import java.net.URI; public class ClientStart { public static void main(String[] args){ try { WebSocketContainer container = ContainerProvider.getWebSocketContainer(); MyClient client = new MyClient(); container.connectToServer(client, new URI("ws://127.0.0.1:8080/myHandler")); // container.setDefaultMaxSessionIdleTimeout(5000L); int turn = 0; while(turn++ < 10){ client.send("client send: 客户端消息 " + turn); Thread.sleep(1000); } }catch (Exception e){ e.printStackTrace(); } } } |
6.执行main方法 OVER ———————————————— 版权声明:本文为CSDN博主「官萧何」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/qq_25613413/article/details/100019875 from:https://www.cnblogs.com/guanxiaohe/p/11727433.html
View DetailsWebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。
WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
借鉴:基于JAVA的功能强大的开源规则引擎-Drools业务管理系统实战视频教程_哔哩哔哩_bilibili 1、什么是规则引擎? 规则引擎,全称为业务规则管理系统,英文名为BRMS(即Business Rule Management System)。规则引擎的主要思想是将应用程序中的业务决策部分分离出来,并使用预定义的语义模板编写业务决策(业务规则),由用户或开发者在需要时进行配置、管理。 需要注意的的规则引擎并不是一个具体的技术框架,而是指的一类系统,即业务规则管理系统。目前市面上具体的规则引擎产品有:drools、VisualRules、iLog等。 规则引擎实现了将业务决策从应用程序代码中分离出来,接收数据输入,解释业务规则,并根据业务规则做出业务决策。规则引擎其实就是一个输入输出平台。 2、Drools介绍 drools是一款由JBoss组织提供的基于java语言开发的开源规则引擎,可以将复杂且多变的业务规则从硬编码中解放出来,以规则脚本的形式存放在文件或特定的存储介质中(如存放在数据库中),使得业务规则的变更不需要修改项目代码、重启服务器就可以在线上环境立即生效。 drools官网:https://www.drools.org/ drools中文网:Drools中文网 | 基于java的功能强大的开源规则引擎 drools源码下载地址:https://github.com/kiegroup/drools 在项目中使用drools时,既可以单独使用也可以整合spring使用。如果单独使用只需导入如下maven坐标即可:
1 2 3 4 5 |
<dependency> <groupId>org.drools</groupId> <artifactId>drools-compiler</artifactId> <version>7.6.0.Final</version> </dependency> |
3、Drools入门案例 1、业务场景说明 业务场景:消费者在图书商城购买图书,下单后需要在支付页面显示订单优惠后的价格。具体优惠规则如下: 现在需要根据上面的规则计算优惠后的价格。 2、开发实现 第一步:创建maven工程并导入drools相关maven坐标
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<!-- drools规则引擎 --> <dependency> <groupId>org.drools</groupId> <artifactId>drools-compiler</artifactId> <version>7.6.0.Final</version> </dependency> <!-- junit单元测试 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> |
第二部:根据drools要求创建resources/META-INF/kmodule.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?xml version="1.0" encoding="UTF-8"?> <kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule"> <!-- name:指定kbase的名称,可以任意,但是需要唯一 packages:指定规则文件的目录,需要根据实际情况填写,否则无法加载到规则文件 default:指定当前kbase是否为默认 --> <kbase name="myKbase1" packages="rules" default="true"> <!-- name:指定ksession的名称,可以任意,但需要唯一 default:指定当前session是否为默认 --> <ksession name="ksession-rule" default="true"/> </kbase> </kmodule> |
注意:上面配置文件的名字和位置都是固定写法,不能更改。 第三步:创建实体类Order
1 2 3 4 5 6 7 8 9 10 11 12 |
package com.ws.soon.entity; import lombok.Data; /** * 订单 */ @Data public class Order { private Double originalPrice; // 订单原始价格,即优惠前的价格 private Double realPrice; // 订单真实价格,即优惠后的价格 } |
第四步:创建规则文件resources/rules/bookDiscount.drl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
// 图书优惠规则 package book.discount import com.ws.soon.entity.Order // 规则一:所购图书总价在100元以下的没有优惠 rule "book_discount_1" when $order: Order(originalPrice < 100) // 匹配模式,到规则引擎中(工作内存)查找Order对象,命名为$order then $order.setRealPrice($order.getOriginalPrice()); System.out.println("成功匹配到规则一,所购图书总价在100元以下无优惠"); end // 规则二:所购图书总价在100~200的优惠20元 rule "book_discount_2" when $order: Order(originalPrice >= 100 && originalPrice < 200) then $order.setRealPrice($order.getOriginalPrice() - 20); System.out.println("成功匹配到规则二,所购图书总价在100~200元之间"); end // 规则三:所购图书总价在200~300元的优惠50元 rule "book_discount_3" when $order: Order(originalPrice >= 200 && originalPrice < 300) then $order.setRealPrice($order.getOriginalPrice() - 50); System.out.println("成功匹配到规则三,所购图书总价在200~300元之间"); end // 规则四:所购图书总价在300元及以上的优惠100元 rule "book_discount_4" when $order: Order(originalPrice >= 300) then $order.setRealPrice($order.getOriginalPrice() - 100); System.out.println("成功匹配到规则四,所购图书总价在300元及以上"); end |
第五步:编写单元测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
package com.ws.soon.test; import com.ws.soon.entity.Order; import org.junit.Test; import org.kie.api.KieServices; import org.kie.api.runtime.KieContainer; import org.kie.api.runtime.KieSession; public class DroolsTest { @Test public void test() { KieServices kieServices = KieServices.Factory.get(); // 获取Kie容器对象(默认容器对象 KieContainer kieContainer = kieServices.newKieClasspathContainer(); // 从Kie容器对象中获取会话对象(默认session对象 KieSession kieSession = kieContainer.newKieSession(); Order order = new Order(); order.setOriginalPrice(160d); // 将order对象插入工作内存 kieSession.insert(order); System.out.println("匹配规则前优惠后价格:" + order.getRealPrice()); // 匹配对象 // 激活规则,由drools框架自动进行规则匹配。若匹配成功,则执行 kieSession.fireAllRules(); // 关闭会话 kieSession.dispose(); System.out.println("优惠前价格:" + order.getOriginalPrice() + "\n优惠后价格:" + order.getRealPrice()); } } |
控制台输出如下: 通过上面的入门案例可以发现,使用drools引擎规则主要工作就是编写规则文件,在规则文件中定义和业务相关的业务规则,例如本案例定义的就是图书的优惠规则。规则定义好后就需要调用drools提供的api将数据提供给规则引擎进行规则模式匹配,规则引擎会执行匹配成功的规则,并将计算的结果返回。 可能大家会有疑问,虽然没有在代码中编写规则的判断逻辑,但是还是在规则文件中编写了业务规则,这跟在代码中编写规则有什么本质的区别? 前面已经提到,使用规则引擎时,规则可以做到动态管理。业务人员可以像管理数据一样对业务规则进行管理,比如查询、添加、更新、统计、提交业务规则等。这样就可以做到在不重启服务的情况下调整业务规则。 4、小结 1、规则引擎构成 drools规则引擎由以下三部分构成: Working Memory(工作内存) Rule Base(规则库) Inference Engine(推理引擎) 其中Inference Engine(推理引擎)又包括: Pattern Matcher(匹配器) Agenda(议程) Execution Engine(执行引擎) 如下图所示: 2、相关概念说明 Working Memory:工作内存,drools规则引擎会从Working Memory中获取数据并和规则文件中定义的规则进行模式匹配,所以我们开发的应用程序只需要将我们的数据插入到Working Memory中即可,例如本案例中我们调用kieSession.insert(order);就是将order对象插入到工作内存中。 Fact:事实,是指在drools规则应用当中,将一个普通的javaBean插入到Working Memory后的对象就是Fact对象,例如本案例中的Order对象就属于Fact对象。Fact对象是我们的应用和规则引擎进行交互的桥梁或通道。 Rule Base:规则库,我们在规则文件中定义的规则都会被加载到规则库中。 Pattern Matcher:匹配器,将Rule Base中的所有规则与Working Memory中的Fact对象进行模式匹配,匹配成功则被激活并放入Agenda中。 Agenda:议程,用于存放通过匹配器进行模式匹配后被激活的规则。 Execution Engine:执行引擎,执行Agenda中被激活的规则。 3、KIE介绍 我们在操作Drools时经常使用的API以及他们之间的关系如下图: 通过上面的API可以发现,大部分类都是以Kie开头。Kie全称为Knowledge is Everything,即“只是就是一切”的缩写,是Jboss一系列项目的总称。如下图所示,Kie的主要模块有OptaPlanner、Drools、UberFire、jBPM。 通过上图可以看到,Drools是整个KIE项目中的一个组件,Drools中还包括一个Drools-WB的模块,他是一个可视化的规则编辑器。 5、Drools基础语法 1、规则文件构成 在使用Drools时非常重要的一个工作就是编写规则文件,通常规则文件的后缀为.drl。 drl是Drools Rule Language的缩写。在规则文件中编写具体的规则内容。 […]
View Details本文实例为大家分享了ASP.NET Core实现文件上传和下载的具体代码,供大家参考,具体内容如下 一、文件上传 1.1 获取文件后缀
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/// <summary> /// 获取文件后缀 /// </summary> /// <param name="fileName">文件名称</param> /// <returns></returns> public async static Task<string> GetFileSuffixAsync(string fileName) { return await Task.Run(() => { string suffix = Path.GetExtension(fileName); return suffix; }); } |
1.2 上传单文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
public class FileMessage { /// <summary> /// 原文件名称 /// </summary> public string FileName { get; set; } /// <summary> /// 附件名称(协议或其他要进行数据库保存与模型绑定的命名) /// </summary> public string ArgumentName { get; set; } /// <summary> /// 文件大小(KB) /// </summary> public string FileSize { get; set; } /// <summary> /// -1:上传失败 0:等待上传 1:已上传 /// </summary> public int FileStatus { get; set; } /// <summary> /// 上传结果 /// </summary> public string UploadResult { get; set; } /// <summary> /// 创建实例 /// </summary> /// <param name="fileName">原文件名称</param> /// <param name="argumentName">(新)附件名称</param> /// <param name="fileSize">大小</param> /// <param name="fileStatus">文件状态</param> /// <returns></returns> public static FileMessage CreateNew(string fileName, string argumentName, string fileSize, int fileStatus, string uploadResult) { return new FileMessage() { FileName = fileName, ArgumentName = argumentName, FileSize = fileSize, FileStatus = fileStatus, UploadResult = uploadResult }; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
/// <summary> /// 上传文件 /// </summary> /// <param name="file">上传的文件</param> /// <param name="fold">要存储的文件夹</param> /// <returns></returns> public async static Task<FileMessage> UploadFileAsync(IFormFile file, string fold) { string fileName = file.FileName; string path = Directory.GetCurrentDirectory() + @"/Upload/" + fold + "/"; if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } string argumentName = DateTime.Now.ToString("yyyyMMddHHmmssfff") + await GetFileSuffixAsync(file.FileName); string fileSize = Math.Round((decimal)file.Length / 1024, 2) + "k"; string filePath = Path.Combine(path, argumentName); try { using (FileStream stream = new FileStream(filePath, FileMode.Create)) { await file.CopyToAsync(stream); } return FileMessage.CreateNew(fileName, argumentName, fileSize, 1, "文件上传成功"); } catch (Exception e) { return FileMessage.CreateNew(fileName, argumentName, fileSize, -1, "文件上传失败:" + e.Message); } } |
1.3 上传多文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
/// <summary> /// 上传多文件 /// </summary> /// <param name="files">上传的文件集合</param> /// <param name="fold">要存储的文件夹</param> /// <returns></returns> public async static Task<List<FileMessage>> UploadFilesAsync(IFormFileCollection files, string fold) { string path = Directory.GetCurrentDirectory() + @"/Upload/" + fold + "/"; if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } List<FileMessage> messages = new List<FileMessage>(); foreach (var file in files) { string fileName = file.FileName; string argumentName = DateTime.Now.ToString("yyyyMMddHHmmssfff") + await GetFileSuffixAsync(file.FileName); string fileSize = Math.Round((decimal)file.Length / 1024, 2) + "k"; string filePath = Path.Combine(path, argumentName); try { using (FileStream stream = new FileStream(filePath, FileMode.Create)) { await file.CopyToAsync(stream); } messages.Add(FileMessage.CreateNew(fileName, argumentName, fileSize, 1, "文件上传成功")); } catch (Exception e) { messages.Add(FileMessage.CreateNew(fileName, argumentName, fileSize, -1, "文件上传失败,失败原因:" + e.Message)); } } return messages; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
[Route("api/[controller]")] [ApiController] public class ManageProtocolFileController : ControllerBase { private readonly string createName = ""; private readonly IWebHostEnvironment _env; private readonly ILogger<ManageProtocolFileController> _logger; public ManageProtocolFileController(IWebHostEnvironment env, ILogger<ManageProtocolFileController> logger) { _env = env; _logger = logger; } /// <summary> /// 协议上传附件 /// </summary> /// <param name="file"></param> /// <returns></returns> [HttpPost("upload")] public async Task<FileMessage> UploadProtocolFile([FromForm] IFormFile file) { return await UploadFileAsync(file, "ManageProtocol"); } } |
二、文件下载 2.1 获取ContentType属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/// <summary> /// 获取文件ContentType /// </summary> /// <param name="fileName">文件名称</param> /// <returns></returns> public async static Task<string> GetFileContentTypeAsync(string fileName) { return await Task.Run(() => { string suffix = Path.GetExtension(fileName); var provider = new FileExtensionContentTypeProvider(); var contentType = provider.Mappings[suffix]; return contentType; }); } |
2.2 执行下载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
[Route("api/[controller]")] [ApiController] public class ManageProtocolFileController : ControllerBase { private readonly string createName = ""; private readonly IWebHostEnvironment _env; private readonly ILogger<ManageProtocolFileController> _logger; public ManageProtocolFileController(IWebHostEnvironment env, ILogger<ManageProtocolFileController> logger) { _env = env; _logger = logger; } /// <summary> /// 下载附件 /// </summary> /// <param name="fileName">文件名称</param> /// <returns></returns> [HttpGet("download")] public async Task<FileStreamResult> Download([FromQuery] string fileName) { try { string rootPath = _env.ContentRootPath + @"/Upload/ManageProtocolFile"; string filePath = Path.Combine(rootPath, fileName); var stream = System.IO.File.OpenRead(filePath); string contentType = await GetFileContentTypeAsync(fileName); _logger.LogInformation("用户:" + createName + "下载后台客户协议附件:" + request.FileName); return File(stream, contentType, fileName); } catch (Exception e) { _logger.LogError(e, "用户:" + createName + "下载后台客户协议附件出错,出错原因:" + e.Message); throw new Exception(e.ToString()); } } } |
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持易盾网络。 from:http://news.558idc.com/448616.html
View Details