企业级-实现Nginx的静态文件服务器映射
作者:fyupeng
技术专栏:☞ https://github.com/fyupeng
项目地址:☞ https://github.com/fyupeng/distributed-blog-system-api
留给读者
开发人员往往会经常需要通过浏览器下载文件、图片或者PDF或者缩略图等,这时候我们可以根据自己的需求自定义设置,安全性就可以由自己来把握。
一、介绍
难点主要在于把文件路径当成参数传给后端,后端根据一定的规则处理,将结果写入响应返回给浏览器。
优点:
- 使用懒加载方式,如果本地有,就不从
OSS获取,本地没有先从OSS下载到本地,以便频繁下载文件时降低OSS的出入流量。 - 待补充
二、代码
/*** @Auther: fyp* @Date: 2024/7/26* @Description: 文件预览处理器* @Package: com.gwssi.common.web* @Version: 1.0*/@Controller
public class FilePreviewController {//本地测试可改为自己的路径//private static final String FILE_DIRECTORY = "D:/upload/";private static final String FILE_DIRECTORY = "/data/hqzr/";@ResponseBody@RequestMapping(value = "/file/{fileUrl}/**", method = RequestMethod.GET)public void getFile(@PathVariable String fileUrl, HttpServletRequest req, HttpServletResponse resp) throws IOException {String path = req.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE).toString();String path2 = req.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE).toString();String args = new AntPathMatcher().extractPathWithinPattern(path2, path);args = args.replace(".do", "");fileUrl = fileUrl + "/" + args;File file = new File(FILE_DIRECTORY + fileUrl);byte[] bytes = null;// 添加安全检查,确保文件确实在预期的目录中if (!file.exists() || !file.isFile() || !file.getCanonicalPath().startsWith(new File(FILE_DIRECTORY).getCanonicalPath())) {// 处理非法访问,例如返回404File parentDir = file.getParentFile();if (!parentDir.exists()) {parentDir.mkdirs(); // 确保文件所在的目录存在}bytes = OssUtil.downloadByBytes(FILE_DIRECTORY + fileUrl);if (null != bytes) {FileOutputStream fos = new FileOutputStream(file);fos.write(bytes);fos.close();resp.reset(); // 非常重要} else {Map<String, String> map = new HashMap<String, String>();map.put("code", "-100");map.put("msg", "文件预览失败");ResponseUtil.returnFrontByJSON(map, resp);}}// 设置适当的响应头(纯下载方式)//resp.setContentType("application/octet-stream; charset=utf-8");//resp.setHeader("Content-Disposition", "attachment;filename=" + file.getName());// 直接预览打开resp.setContentType("image/png"); // 设置返回的文件类型resp.addHeader("Content-Length", String.valueOf(file.length())); //文件大小// 使用ServletOutputStream将图片数据写入响应try (ServletOutputStream outputStream = resp.getOutputStream();BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(file))) {// 从文件服务器获取if (null != bytes) {outputStream.write(bytes);} else {// 从本地获取byte[] buffer = new byte[4096];int bytesRead = -1;// 读取文件内容并写入响应while ((bytesRead = inputStream.read(buffer)) != -1) {outputStream.write(buffer, 0, bytesRead);}}// 刷新输出流,确保所有数据都被发送outputStream.flush();}}private String getMimeType(File file) {// 这里可以根据文件扩展名返回相应的MIME类型// 这里只是一个简单的示例,实际应用中可能需要更复杂的逻辑String filename = file.getName().toLowerCase();if (filename.endsWith(".png")) {return MediaType.IMAGE_PNG_VALUE;} else if (filename.endsWith(".jpg") || filename.endsWith(".jpeg")) {return MediaType.IMAGE_JPEG_VALUE;}// 添加更多MIME类型判断...return MediaType.APPLICATION_OCTET_STREAM_VALUE; // 默认类型}
}
三、总结
简洁、高效、实用!
相关文章:
企业级-实现Nginx的静态文件服务器映射
作者:fyupeng 技术专栏:☞ https://github.com/fyupeng 项目地址:☞ https://github.com/fyupeng/distributed-blog-system-api 留给读者 开发人员往往会经常需要通过浏览器下载文件、图片或者PDF或者缩略图等,这时候我们可以根据…...
CTF Web SQL注入 10000字详解
这里写目录标题 涉及的数据库知识unionorder bydatabase()information_schemalimit--空格注释replaceinto outfilelikeGROUP BYHAVINGGROUP BY、HAVING、WHERE之间的关系regexp 原理信息收集操作系统数据库判断注入点注入点类型POST注入数字型注入字符型注入搜索型注入Insert/u…...
动态SLAM:如何判断一个特征是动态特征(对极几何)
文章目录 1.什么是极线、极点和极面2.如何判断其为动态点特征3.如何判断其为动态线特征 1.什么是极线、极点和极面 由图可知,C1,C2,X(X1,X2)组成了一个三角平面,这个三角所在的平面就是极面 在这个极平面中,和成像平面相交的线是极线…...
【C++】初识C++基础篇·一(命名空间,函数重载,缺省参数,引用);
文章目录 前言1.输入与输出输出输入cin和scanf的对比 2.命名空间2.1namespace存在的意义2.2namespace的使用3.缺省参数4.函数重载重载函数的调用规则 5.引用 前言 我们先通过一段简单的代码来拉开C的序幕; //text.cpp #include<iostream> #include<stdio…...
2024年道路运输安全员考试题库及答案
一、判断题 1.国家制订《中华人民共和国道路交通安全法》的目的是为了维护道路交通秩序,预防和减少交通事故,保护人身安全,保护公民、法人和其他组织的财产安全及其他合法权益,提高通行效率。 答案:正确 2.依据《中…...
Linux Vim教程(十二):语法高亮与代码折叠
目录 1. 语法高亮 1.1 启用语法高亮 1.2 设置配色方案 1.3 自定义语法高亮 2. 代码折叠 2.1 启用代码折叠 2.2 设置折叠方法 2.3 手动折叠 2.4 基于缩进的折叠 2.5 基于语法的折叠 3. 案例 3.1 配置文件 3.2 编辑Python文件 3.3 使用折叠功能 4. 高级使用技巧 …...
JavaScript(18)——事件类型,事件对象
事件类型 鼠标事件: click:鼠标点击 mouseenter:鼠标经过 mouseleave:鼠标离开 焦点事件: focus:获得焦点 blur:失去焦点 键盘事件: Keydown:键盘按下触发 Keyup&#…...
有效组织离散变量:指针数组在C语言中的应用
把离散变量组织起来,访问起来更加方便,无需一个个变量单独赋值。 如modbus读写reg, 把a\b\c\d实时变化分散的变量组织成一个数组reg,方便获取 相当于变量的内存地址池 int main() {int a 10, b 20, c 30, d 40;int i;int *re…...
qt 应用正在运行时,如何更新升级exe文件
在Qt应用正在运行时,直接替换同名的.exe文件可能会导致文件正在使用中的错误。为了安全地更新.exe文件,你可以采取以下步骤: 创建一个临时的.exe文件。 等待当前.exe文件的进程关闭。 删除原有的.exe文件。 将临时.exe文件重命名为原有的.…...
git的rebase 和 merge 的区别
rebase 和 merge 的区别 Merge(合并)和 Rebase(变基)是 Git 中两种常用的分支整合方式,它们有不同的工作原理和适用场景: Merge(合并): ● Merge 操作将两个分支的不同提…...
django基于大数据的电影推荐系统-计算机毕业设计源码71246
目 录 摘 要 1 绪论 1.1 选题背景与意义 1.2研究现状 1.3研究内容 1.4 开发环境 1.5论文结构与章节安排 2 相关理论和技术 2.1 协同过滤算法 2.2 B/S体系结构介绍 2.3 Python爬虫技术 2.4 Django框架介绍 2.5 MySQL数据库 3 电影推荐系统系统分析 3.1 可行性分析…...
reverse_re3-入土为安的第十天
一个迷宫题 shirtf12发现flag字样 点进去发现迷宫 675 应该是3 * 15*15 即有三个迷宫 shifte提取 import numpy as np# 你的数据(长度应为 225 的倍数) dword_202020 [1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,3,1,1,0,0,0,0,0,0,1,1,1,1,1,0,0,…...
fastapi之一
文章目录 安装运行HTTP 请求方法示例 POSTMAN 检验GETPOSTPUTDELETE HTTP 状态码示例GETPOST 综合示例POSTGETPUTDELETE 总结 安装 pip install fastapi或者 pip install fastapi -i https://mirrors.aliyun.com/pypi/simple上面两种方法均可以,选择一个即可&…...
【C语言报错已解决】Format String Vulnerability
🎬 鸽芷咕:个人主页 🔥 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 引言 在日常开发中,我们经常会遇到各种各样的bug,其中格式化字符串漏洞报错可能是最让人头疼的一种。这…...
关于一个简单的顺序表代码
1.首先是头文件SeqList.h的代码: #pragma once #include<stdio.h> #include<assert.h> #include<stdlib.h> typedef int SXBint; typedef struct SL {SXBint* a;int size;int capacity; }SLnode; //初始化 void SeqLsitInit(SLnode* ps); //尾插…...
【资料分享】2024第三届钉钉杯大学生大数据挑战赛B题思路解析+双语言代码
2024钉钉杯大学生大数据挑战赛,B题解题思路和双语言代码分享,资料预览:...
Typescript学习笔记(2.0)
ts编译选项 tsc app.ts -w 参数-w,就是对app.ts进行监视,每次该文件改变时就会自动编译 **:任意目录 *:任意文件 接口 接口用来定义一个类结构,用来定义一个类中应该包含哪些属性和方法,同时接口也可以当做类型…...
【IJHE】:微通道反应器中全氢二苄基甲苯脱氢产氢
Highlight 微通道反应器中全氢二苄基甲苯脱氢产氢两种不同反应器的比较:搅拌釜和连续微通道反应器连续微通道反应器是一种很有前途的脱氢技术 摘要: 本文对全氢二苄基甲苯作为液态有机氢载体从搅拌槽反应器转换为连续流微通道反应器进行脱氢进行了初步研究。与搅拌槽…...
Spring踩坑:抽象类作为父类,使用子类@Autowired属性进行填充,属性值为null
Spring踩坑:抽象类作为父类,使用子类Autowired属性进行填充,属性值为null Spring Boot中抽象类和依赖注入的最佳实践引言在抽象类中使用Autowired注解protected vs private修饰符低版本Spring Boot的注意事项 构造器中的依赖注入陷阱为什么不…...
C#网络连接:TCP/IP模式下的网络连接与同步
1,目的 为了测试局域网的消息同步,简单写了下TCP/IP模式的同步,参考这个帖子。 2,核心库部分 using System; using System.Net; using System.Net.Sockets; using System.Text;namespace Coldairarrow.Util.Sockets {/// <s…...
第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...
dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...
SpringCloudGateway 自定义局部过滤器
场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...
