Java 图片文件上传下载处理

Java 图片文件上传下载处理

  • 下载

做这玩意给我恶心坏了

下载

直接访问上传的路径就可以下载图片了。但是我们往往会包一层接口,以流的方式读取 url 的内容然后返回给前端,这么做的优点是:

  • 内网域名转外网域名,做业务校验并且让用户可以访问内网数据
  • 为所有的后端预览做一个统一的出口
  • 让访问的图片支持跨域

这么做的一般代码为

    void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String fileName = request.getParameter("file_name");OutputStream out = response.getOutputStream();String url = request.getParameter("file_path");byte[] bytes;// 读取流数据VacationClient2 vc = new VacationClient2(2000, 5000);byte[] bs = vc.getContentBytes(url);// 一般返回的是 base64 串,但是有可能会返回一般的字符串,不需要做 base64 解码时做个判断处理一下if (url.matches("^.*imgs\\.qunarzz\\.com.*\\.$")) {bytes = bs;} else {String newString = new String(bs);// 替换所有的空格到+newString = newString.replaceAll(" ", "+");bytes = new BASE64Decoder().decodeBuffer(newString);}downloadFileUnderHttps(request, response, fileName, bytes);out.write(bytes);out.flush();out.close();}

讲一下 base64 是什么:

  • Base64 是一种基于 64 个可打印字符来表示二进制数据的表示方法,由于 2^6=64,所以每 6 个比特为一个单元,对应某个可打印字符
  • Base64 常用于在通常处理文本数据的场合,表示、传输、存储一些二进制数据,包括 MIME 的电子邮件及 XML 的一些复杂数据
  • Base64 编码要求把 3 个 8 位字节(38=24)转化为 4 个 6 位的字节(46=24),之后在 6 位的前面补两个 0,形成 8 位一个字节的形式。 如果剩下的字符不足 3 个字节,则用 0 填充
  • Base64 编码后的输出还是按照 UTF-8 来输出

为什么要使用 Base64?

  • 存储二进制数据:在某些情况下,需要将二进制数据存储到文本文件中,例如将图片或音频文件存储到数据库或文本文件中。由于文本文件只能存储文本数据,无法直接存储二进制数据,因此可以将二进制数据转换为 Base64 编码的文本,然后存储到文本文件中
  • URL传参:在 URL 中传递参数时,某些字符可能会被 URL 编码,或者传的参数被误解为 url 的连接符,导致传递的参数变得很长。通过将参数进行 Base64 编码,可以将参数转换为可打印的 ASCII 字符,减少URL长度。

总之,使用 Base64 编码可以方便地将二进制数据转换为可打印的 ASCII 字符,以便在网络传输或存储到文本文件中

为了保证所输出的编码位可读字符,Base64 制定了一个编码表,以便进行统一转换。编码表的大小为 2^6=64,这也是 Base64 名称的由来
在这里插入图片描述

在 Base64 中的可打印字符包括字母 A-Z、a-z、数字 0-9,这样共有 62 个字符,此外两个可打印符号在不同的系统中而不同

以下是 Base64 编码的基本步骤:

  • 将数据划分为 3 个字节一组(24位)
  • 将每个字节转换为 8 位二进制形式
  • 将 24 位数据按照 6 位一组进行划分,得到 4 个 6 位的组
  • 将每个 6 位的组转换为对应的 Base64 字符
  • 如果数据不足 3 字节,进行填充
  • 将所有转换后的 Base64 字符连接起来,形成最终的编码结果
  • 解码 Base64 编码的过程与编码相反,将每个 Base64 字符转换为对应的6位二进制值,然后将这些 6 位值组合成原始的二进制数据

Base64 编码具有以下特点:

  • 编码后的数据长度总是比原始数据长约 1/3
  • 编码后的数据可以包含 A-Z、a-z、0-9 和两个额外字符的任意组合
  • Base64 编码是一种可逆的编码方式,可以通过解码还原原始数据

编码 Man 的结果为 TWFu,转换过程如下:
在这里插入图片描述

此外还有一个问题,Base64 加密后的数据通过 http 传输后,后台接收到的数据可能会出现空格的问题。这个问题还不知道具体原因

  • 加号(+):url 编码后,会用 %2 替换原来位置的 +。这里 url 的编码规则是符号的 Unicode 值前面加一个 %。因此 + 对应的是 %2B,空格则是 %20
  • form 表单提交,默认是 application/x-www-form-urlencoded,因此会对参数进行 urlencode

最后,贴一下响应头的代码:

    public static void downloadFileUnderHttps(HttpServletRequest request,HttpServletResponse response,String filename, byte[] fileBytes) throws UnsupportedEncodingException {String agent = request.getHeader("User-Agent");filename = filename.replaceAll("filename=", "");if (agent != null && agent.indexOf("Windows") != -1) {filename = new String(filename.getBytes("GB2312"), "ISO_8859_1");} else {filename = new String(filename.getBytes("UTF-8"), "ISO_8859_1");}// 通过文件开头获取文件类型String contentType = FileTypeUtil.getFileContentType(fileBytes);if (StringUtils.isNotBlank(contentType)) {response.setContentType(contentType);response.addHeader("Content-Disposition", "inline; filename=\"" + filename + "\"");} else {response.setContentType("APPLICATION/OCTET-STREAM");response.addHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");response.setHeader("Content-Transfer-Encoding", "binary");}response.setCharacterEncoding("UTF-8");response.setHeader("Pragma", "public");response.setHeader("Cache-Control", "public");}

常见的文件开头如下:

  • JPEG (jpg),文件头:FFD8FFE1
  • PNG (png),文件头:89504E47
  • GIF (gif),文件头:47494638
  • TIFF (tif),文件头:49492A00
  • Windows Bitmap (bmp),文件头:424D
  • CAD (dwg),文件头:41433130
  • Adobe Photoshop (psd),文件头:38425053
  • Rich Text Format (rtf),文件头:7B5C727466
  • XML (xml),文件头:3C3F786D6C
  • HTML (html),文件头:68746D6C3E

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

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

相关文章

后端相关随机题目记录(1)

目录 后端相关随机题目记录(1) 后端相关随机题目记录(1)Bean的类型以及作用域Bean的生命周期Mysql的底层数据结构RedisHttp和Https区别AOP在项目的应用 自定义注解?请求在spring中的一个流程Nacos与zk的区别SpringMV…

Unity中URP下的菲涅尔效果实现(个性化修改)

文章目录 前言一、我们修正一下上篇文章中,可能遗留的Bug1、N向量 变为 单位向量2、使颜色范围在合理区间 二、实现菲涅尔效果强弱可自定义调节三、修改菲涅尔效果颜色1、在属性面板定义颜色属性2、在常量缓冲区申明该参数3、在片元着色器中,用颜色和菲涅…

Python---进程

1. 进程的介绍 在Python程序中,想要实现多任务可以使用进程来完成,进程是实现多任务的一种方式。 2. 进程的概念 一个正在运行的程序或者软件就是一个进程,它是操作系统进行资源分配的基本单位,也就是说每启动一个进程&#xf…

QT for Android安卓编译环境搭建+首次编译3个大坑

1、安装 编译环境能否搭建成功,主要是看各个依赖软件的版本是否匹配。依赖的软件有3个:JDK、安卓SDK、安卓NDK。 我的qt版本是5.14.1,我亲测以下版本可以成功让编译安卓: QT5.14 JDK1.8.0 安卓SDK26.1 安卓NDK20.1 在QT-&g…

LeetCode 142. 环形链表 II

给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整…

【网络安全】-Linux操作系统—操作系统发展历史与Linux

文章目录 操作系统发展历史初期的操作系统分时操作系统个人计算机操作系统 Linux的诞生UNIX与GNU项目Linux内核的创建 Linux的特点开放源代码多样性社区支持 Linux的应用服务器和超级计算机嵌入式系统桌面系统 总结 操作系统发展历史 操作系统(Operating System&am…

Linux之FTP 服务器

一、FTP服务器匿名账户服务器配置 1、测试是否已安装vsftp服务器: 2、启动vsftp服务器: 3、修改vsftp主配置文件,允许匿名登录 4、重新启动vsftpd服务,禁用防火墙 5、打开FTP服务的数据文件存放目录/var/ftp,复制若干文件到该目…

Java小案例-RocketMQ的11种消息类型,你知道几种?(死信消息)

前言 在RocketMQ中,死信消息(Dead-Letter Message)是指那些在正常情况下无法被消费者消费的消息。这些消息会被存储在死信队列(Dead-Letter Queue,简称DLQ)中。 死信消息的特性包括: 不会再被…

DC-4靶场

目录 nmap进行主机发现 尝试反弹shell: 进入交互式shell: Hydra爆破jim用户密码: ssh登录charles : 提权(三种方法): exim4提权…

智能优化算法应用:基于社会群体算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用:基于社会群体算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于社会群体算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.社会群体算法4.实验参数设定5.算法结果6.…

PIC单片机项目(4)——基于PIC16F877A的温度光照检测装置

1.功能设计 基于PIC16F877A单片机,使用DS18B20进行温度测量,使用光敏电阻进行光照测量,将测量值实时显示在LCD1602屏幕上,同时可以设定光照阈值和温度阈值。当温度大于阈值,则蜂鸣器报警,当光照小于阈值&am…

【源码解析】Semaphore角度聊聊AQS

案例 Semaphore,俗称信号量,它是操作系统中PV操作的原语在java的实现,它也是基于 AbstractQueuedSynchronizer实现的 private static ExecutorService threadPool Executors.newFixedThreadPool(4);private static Semaphore semaphore ne…

设计模式——结构型

1.装饰器模式 要素:装饰器,装饰对象 为待装饰对象中某一结构特征添加内容,而不是新建一个特征 /*** 装饰对象*/ public interface Shape {public void draw(); } /*** 具体装饰对象*/ public class Circle implements Shape{private String…

计算机组成原理——校验码

计算机组成原理学习笔记——校验码-CSDN博客 校验码——海明码及码距,码距_海明码的码距是多少-CSDN博客 1 下列关于码距与检错与纠错能力的描述中正确的是 (ABC) (多选) A. 码距为1的编码不具备任何检错能力 B. 码…

社交网络分析4(上):社交网络链路预测分析、Logistic回归模型、LLSLP方法(LightGBM 堆叠链路预测)、正则化方法、多重共线性

社交网络分析4 写在最前面社交网络链路预测分析概述链路预测分析简介链路预测分析的重要性社交网络链路预测分析方法基于网络结构的方法基于节点属性的方法基于随机游走的方法基于深度学习的方法 基于相似性和基于似然性的链路预测方法基于相似性的方法基于邻居的方法基于路径的…

Linux shell编程学习笔记36:read命令

*更新日志 *2023-12-18 1.根据[美] 威廉肖特斯 (Willian shotts)所著《Linux命令行大全(第2版)》 更新了-e、-i、-r选项的说明 2.更新了 2.8 的实例,增加了gif动图 3.补充了-i的应用实例 2.1…

回归预测 | MATLAB实现SABO-LSTM基于减法平均优化器优化长短期记忆神经网络的多输入单输出数据回归预测模型 (多指标,多图)

回归预测 | MATLAB实现SABO-LSTM基于减法平均优化器优化长短期记忆神经网络的多输入单输出数据回归预测模型 (多指标,多图) 目录 回归预测 | MATLAB实现SABO-LSTM基于减法平均优化器优化长短期记忆神经网络的多输入单输出数据回归预测模型 &a…

自清洗过滤器工作原理尺寸选型参数,内部结构,压差开关如何调节

​ 1:全自动自清洗过滤器设备介绍 全自动反冲洗过滤器是水净化过程中不可缺少的处理手段,用于拦截水中的各种杂质,以净化水质或保护系统中其他设备的正常工作。普通网式过滤器因其结构简单、过滤效果好、阻力小而广泛应用于水源过滤、工业循…

神经网络可以计算任何函数的可视化证明

神经网络可以计算任何函数的可视化证明 对于神经网络,一个显著的事实就是它可以计算任何函数。 如下:不管该函数如何,总有神经网络能够对任何可能的输入x,输出值f(x) 即使函数有很多输入和输出&#xff0…

Git提交前的必备神器——自动清除调试语句脚本

说在前面 不知道大家有没有遇到这样一种情况,平时在写代码调试时有时候会使用到debugger,可能大部分时间在提交代码前会记得把debugger先删除,但可能也会存在将debugger提交上去的情况,那我们该怎么防止出现这种情况呢&#xff1f…