网站常用布局/合肥今天的最新消息
背景
FTP文件服务器在我们日常开发中经常使用,在项目中我们经常把FTP文件下载到内存中,然后转为base64给前端进行展示。如果excel中也需要导出图片,数据量大的情况下会直接返回一个后端的开放接口地址,然后在项目中对接口的参数进行鉴权,或者实效性检验等,最后从FTP下载图片用流的方式传到浏览器中。
但是这种方式会加大内存的消耗,所有的文件相关的都在内存中下载回传给前端;报表下载的数据量很大的情况下服务很容易拖垮。所以就设想通过两层nginx反向代理的方式是否可以满足文件的直接访问。
假设FTP文件服务器的照片存放地址为:/upload/signature
传统实现
首先我们在下载excel的时候需要组装一个url,如下所示的get请求就是一个对外开放无需权限的接口,真实情况下会对realFilePath进行加密组装,里面放一些timestamp或者redis的key来验证实效性、安全性等。
@GetMapping("/signatureImage/{path}")public void signatureImage(@PathVariable("path") String realFilePath, HttpServletResponse response) throws IOException {//realFilePath = "/20231206/qhyu.png"String fileName = "qhyu.png"; //可以切割获取。String path = "/upload/signature"; // 固定的存放路径ByteArrayOutputStream outputStream = new ByteArrayOutputStream();try (Ftp ftp = new Ftp("Ftp_address", "Ftp_port", "username", "password")) {ftp.download(path+realFilePath, fileName, outputStream);} catch (Exception e) {log.error("FTP文件下载出错:{}", e.getMessage());throw new QhyuException(MessageCode.FILE_DOENLOAD_ERROR.getCode());}// 将内存中的文件内容转换为输入流InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());// 设置响应的内容类型为图片格式String contentType = MediaType.IMAGE_PNG_VALUE; // 假设为PNG格式response.setContentType(contentType);org.apache.commons.io.IOUtils.copy(inputStream, response.getOutputStream());response.flushBuffer();// 关闭内存流和FTP连接inputStream.close();outputStream.close();}
Nginx实现
要通过Nginx实现的话,基本上网上的方案都是让使用lua。虽然可以但是没必要。因为我从官网上找到了解决方案,如下所示。
提供一下proxy相关参数的含义:
proxy_set_header Host $host;
:
此参数设置了将客户端请求中的Host头部信息传递给代理服务器。$host变量表示客户端请求中的主机名。proxy_intercept_errors on;
:
当启用此参数时,代理服务器会拦截后端服务器返回的错误响应,并将其作为代理服务器的响应返回给客户端。这允许代理服务器处理后端服务器的错误响应,并可以进行自定义的错误处理。proxy_set_header X-Real-IP $remote_addr;
:
此参数设置了将客户端的真实IP地址传递给代理服务器。$remote_addr变量表示客户端的IP地址。proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
:
此参数设置了将客户端的IP地址添加到X-Forwarded-For头部信息中。$proxy_add_x_forwarded_for变量表示将客户端IP地址添加到现有的X-Forwarded-For头部信息中。proxy_buffering off;
:
当启用此参数时,禁用代理缓冲。代理缓冲可以在接收完整的响应后再将其发送给客户端,以提高性能和效率。禁用缓冲意味着代理服务器会立即将收到的数据发送给客户端,适用于需要实时数据传输的场景。
下面就是我的nginx配置:
server {listen 10086;charset utf-8;access_log /var/log/nginx/qhyu/qhyu_access.log;error_log /var/log/nginx/qhyu/qhyu_error.log;location /verify {proxy_pass http://host:port/api/signatureImage/validate?realFilePath=$arg_realFilePath&signature=$arg_signature;proxy_set_header Host $host;proxy_intercept_errors on;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_buffering off;error_page 418 = @custom_redirect;error_page 420 = @custom_error;}location @custom_error{default_type application/json;return 200 'error image';}location @custom_redirect {rewrite ^ /signature/$arg_realFilePath last;}location /signature {alias /upload/signature/;}
}
}
然后就是编写了一个接口,也就是在调用的时候可以访问/verify接口带上参数,就会跳转到这个接口进行校验,如果返回的http状态码是418说明校验通过,如果返回的是420说明校验失败。
@GetMapping("/signatureImage/validate")public Object signatureValidate(String realFilePath,String signature,HttpServletResponse httpServletResponse){String redisKey = AesEncryptUtil.decryption(signature);if (StrUtil.isBlank(redisKey)){httpServletResponse.setStatus(420);return RenderResult.success();}Object value = redisService.get(redisKey);if (value == null) {httpServletResponse.setStatus(420);return RenderResult.success();}List<String> signatureUrls = JSON.parseArray(JSON.toJSONString(value), String.class);if (signatureUrls == null || signatureUrls.isEmpty()){httpServletResponse.setStatus(420);return RenderResult.success();}if (!signatureUrls.contains(realFilePath)){httpServletResponse.setStatus(420);return RenderResult.success();}// greater than or equal to 300 should be passed to a client or be intercepted and redirected to nginx// for processing with the error_page directive// http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_intercept_errorshttpServletResponse.setStatus(418);return RenderResult.success();}
分析结果
nginx的实现方式在校验失败的时候页面返回error image,跳转的是420 error_page;成功的时候会访问FTP文件服务器的路径,反正图片到页面展示。在实际的开发过程中,外层可能还会有一个nginx反向代理,本文主要讲解了一下如何使用这个方式对访问的文件进行鉴权。
这样做的好处就是不需要每个文件都下载到内存然后使用流的方式传输,直接访问的方式减少了后端服务的压力,并且像头像、签名这种可能访问频繁的接口使用这种方式来处理是很棒的一种方式。
主要的思路就是拿到proxy_pass的返回信息,如果使用lua的话可以获取到我们返回的body内容,但是不使用lua的时候我们可以迂回处理,使用status code也一样可以达到目的。
相关文章:

Nginx访问FTP服务器文件的时效性/安全校验
背景 FTP文件服务器在我们日常开发中经常使用,在项目中我们经常把FTP文件下载到内存中,然后转为base64给前端进行展示。如果excel中也需要导出图片,数据量大的情况下会直接返回一个后端的开放接口地址,然后在项目中对接口的参数进…...

【VSCode】自定义配置
VSCode自定义配置 Visual Studio Code (VSCode) 是一个强大的开源代码编辑器,支持丰富的自定义配置。下面是一些常见的自定义配置选项,你可以根据个人喜好和工作流程进行调整: 1. 主题和配色方案: 在 “settings.json” 中设置:…...

SpringBoot整合Kafka (一)
📑前言 本文主要讲了SpringBoot整合Kafka文章⛺️ 🎬作者简介:大家好,我是青衿🥇 ☁️博客首页:CSDN主页放风讲故事 🌄每日一句:努力一点,优秀一点 目录 文章目录 &…...

随机分词与tokenizer(BPE->BBPE->Wordpiece->Unigram->sentencepiece->bytepiece)
0 tokenizer综述 根据不同的切分粒度可以把tokenizer分为: 基于词的切分,基于字的切分和基于subword的切分。 基于subword的切分是目前的主流切分方式。subword的切分包括: BPE(/BBPE), WordPiece 和 Unigram三种分词模型。其中WordPiece可以认为是一种特殊的BPE。完…...

成都工业学院Web技术基础(WEB)实验四:CSS3布局应用
写在前面 1、基于2022级计算机大类实验指导书 2、代码仅提供参考,前端变化比较大,按照要求,只能做到像,不能做到一模一样 3、图片和文字仅为示例,需要自行替换 4、如果代码不满足你的要求,请寻求其他的…...

TikTok科技趋势:平台如何引领数字社交革命?
TikTok作为一款颠覆性的短视频应用,不仅改变了用户的娱乐方式,更在数字社交领域引领了一场革命。本文将深入探讨TikTok在科技趋势方面的引领作用,分析其在数字社交革命中的关键角色,以及通过技术创新如何不断满足用户需求…...

【上海大学数字逻辑实验报告】六、时序电路
一、 实验目的 掌握同步二进制计数器和移位寄存器的原理。学会用分立元件构成2位同步二进制加计数器。学会在Quartus II上设计单向移位寄存器。学会在Quartus II上设计环形计数器。 二、 实验原理 同步计数器是指计数器中的各触发器的时钟脉冲输入端连接在一起,接…...

docker版zerotier-planet服务端搭建
1:ZeroTier 介绍2:为什么要自建PLANET 服务器3:开始安装 3.1:准备条件 3.1.1 安装git3.1.2 安装docker3.1.3 启动docker3.2:下载项目源码3.3:执行安装脚本3.4 下载 planet 文件3.5 新建网络 3.5.1 创建网络4.客户端配置 4.1 Windows 配置 4.2 加入网络4.2 Linux 客户端4.…...

【Spring教程28】Spring框架实战:从零开始学习SpringMVC 之 请求与请求参数详解
目录 1 设置请求映射路径1.1 环境准备 1.2 问题分析1.3 设置映射路径 2 请求参数2.1 环境准备2.2 参数传递2.2.1 GET发送单个参数2.2.2 GET发送多个参数2.2.3 GET请求中文乱码2.2.4 POST发送参数2.2.5 POST请求中文乱码 欢迎大家回到《Java教程之Spring30天快速入门》ÿ…...

node.js和浏览器之间的区别
node.js是什么 Node.js是一种基于Chrome V8引擎的JavaScript运行环境,可以在服务器端运行JavaScript代码 Node.js 在浏览器之外运行 V8 JavaScript 引擎。 这使得 Node.js 非常高效。 浏览器如何运行js代码 nodejs运行环境 在浏览器中,大部分时间你所…...

【python并发任务的几种方式】
文章目录 1 Process:2 Thread:3 ThreadPoolExecutor:4 各种方式的优缺点:5 线程与进程的结束方式5.1 线程结束的几种方式5.2 进程的结束方式 6 应用场景效率对比 在Python中,有几种方法可以处理并行执行任务。其中,Process、Thread和ThreadPo…...

使用ROS模板基于ECS和RDS创建WordPress环境
本文教程介绍如何使用ROS模板基于ECS和RDS(Relational Database Service)创建WordPress环境。 前提条件 如果您是首次使用ROS,必须先开通ROS服务。ROS服务免费,开通服务不会产生任何费用。 背景信息 WordPress是使用PHP语言开…...

龙迅LT2611UXC 双PORT LVDS转HDMI(2.0)+音频
描述: LT2611UXC是一个高性能的LVDS到HDMI2.0的转换器,用于STB,DVD应用程序。 LVDS输入可配置为单端口或双端口,有1个高速时钟通道,3~4个高速数据通道,最大运行1.2Gbps/通道,可支持高达9.6Gbp…...

websocket和SSE通信示例(无需安装任何插件)
websocket和SSE通信示例(无需安装任何插件) 源码示例(两种方案任意切换) data(){return {heartBeatInterval:5000,// 心跳间隔时间,单位为毫秒webSocket:null,heartBeatTimer:null,} }, mounted() {// this.initWebS…...

计算机网络(三)
(十一)路由算法 A、路由算法分类 动态路由和静态路由 静态路由:人工配制,路由信息更新慢,优先级高。这种在实际网络中要投入成本大,准确但是可行性弱。 动态路由:路由更新快,自动…...

HttpURLConnection OOM问题记录
使用HttpURLConnection 上传大文件,会出现内存溢出问题: 观察HttpURLConnection 源码: Overridepublic synchronized OutputStream getOutputStream() throws IOException {connecting true;SocketPermission p URLtoSocketPermission(th…...

WT588F02B单片机语音芯片在磁疗仪中的应用介绍
随着健康意识的普及和科技的发展,磁疗仪作为一种常见的理疗设备,受到了广大用户的关注。为了提升用户体验和操作便捷性,唯创知音WT588F02B单片机语音芯片被成功应用于磁疗仪中。这一结合将为磁疗仪带来智能化的语音交互功能,为用户…...

深度学习——第5章 神经网络基础知识
第5章 神经网络基础知识 目录 5.1 由逻辑回归出发 5.2 损失函数 5.3 梯度下降 5.4 计算图 5.5总结 在第1课《深度学习概述》中,我们介绍了神经网络的基本结构,了解了神经网络的基本单元组成是神经元。如何构建神经网络,如何训练、优化神…...

微信网页授权步骤说明
总览 引导用户进入授权页面同意授权,获取code通过code换取网页授权access_token(与基础支持中的access_token不同)如果需要,开发者可以刷新网页授权access_token,避免过期(一般不需要)通过网页…...

linux bash shell变量操作符 —— 筑梦之路
1. 变量子串 ${var} 返回变量var的内容,单独使用时有没有{}一样,混合多个变量和常量时,用{}界定变量名 ${#var} 返回变量var内容的长度 ${var:offset} 从变量var中的偏移量offset开始截取到字符串结尾的子字符串,offset从0开始 ${…...

2.61【Python生成器与迭代器】
Python迭代器与生成器 迭代器 什么是迭代器 首先迭代是指python中访问元素的一种方式,迭代器是一个可以记住遍历位置的对象,因此不会像列表那样一次性全部生成,而是可以等到用的时候才生成,因此节省了大量的内存资源 可迭代对…...

devecho stuido npm 失败
使用华为推荐的设置npm 代理方式仍然无效。还是得使用npm 命令去设置代理。地址参考: npm设置和取消代理的方法_npm查看代理-CSDN博客 最后使用自己的代理加载成功,使用华为推荐的代理不成功,不清楚什么原因。 华为推荐的环境配置如下&…...

postgreSql逻辑复制常用语句汇总和说明
简单说明 postgreSql逻辑复制的原理这里不再赘述,度娘一下即可。这里只是对常用的语句做一些汇总和说明,以便日后查找时方便。 逻辑复制的概念 逻辑复制整体上采用的是一个发布订阅的模型,订阅者可以订阅一个或者多个发布者, 发…...

设置Ubuntu或树莓派系统,允许root用户ssh方式连接
Ubuntu 或 Raspbian 系统默认不允许root 用户以ssh方式连接。连接会报如下错误: Permission denied, please try again. 解决步骤: (如果是树莓派系统:烧录到内存卡后,拔掉内存卡再重新插到PC机上&#x…...

Ubuntu安装向日葵【远程控制】
文章目录 引言下载向日葵安装向日葵运行向日葵卸载向日葵参考资料 引言 向日葵是一款非常好用的远程控制软件。这一篇博文介绍了如何在 Ubuntu Linux系统 中安装贝瑞向日葵。🏃💥💥💥❗️ 下载向日葵 向日葵官网: https://sunl…...

jquery 实现倒计时60秒
jquery 实现倒计时60秒 <!DOCTYPE html> <html><head><meta http-equiv"content-type" content"text/html; charsetUTF-8"><meta content"widthdevice-width,initial-scale1.0,maximum-scale1.0,user-scalableno" i…...

单例模式:饿汉模式、懒汉模式
目录 一、什么是单例模式 二、饿汉模式 三、懒汉模式 一、什么是单例模式 单例模式是Java中的设计模式之一,能够保证某个类在程序中只存在唯一一份实例,而不会创建出多个实例 单例模式有很多实现方式,最常见的是饿汉和懒汉两种模式 二、…...

提升方法AdaBoost
通过改变训练样本的权重学习多个分类器,并将这些线性分类器进行线性组合,提高分类性能。 AdaBoost 提高前一轮被分类错误的权值,降低前一轮被分类正确的权值;加大分类误差错误率小的弱分类器权重。 算法: 输入&…...

Python自动化测试系列[v1.0.0][多种数据驱动实现附源码]
前情提要 请确保已经熟练掌握元素定位的常用方法及基本支持,请参考Python自动化测试系列[v1.0.0][元素定位] 数据驱动测试是自动化测试中一种重要的设计模式,这种设计模式可以将测试数据和测试代码分开,实现数据与代码解耦,与此同…...

【论文笔记】Gemini: A Family of Highly Capable Multimodal Models——细看Gemini
Gemini 【一句话总结,对标GPT4,模型还是transformer的docoder部分,提出三个不同版本的Gemini模型,Ultra的最牛逼,Nano的可以用在手机上。】 谷歌提出了一个新系列多模态模型——Gemini家族模型,包括Ultra…...