Java 图片文件上传下载处理

news2024/11/27 15:45:34

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.coloradmin.cn/o/1320498.html

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

相关文章

【C++】new 和 delete

目录 一 引言 二 new 三 delete 四 new和delete操作自定义类型 五 operator new与operator delete函数 六 new和delete的实现原理 1 内置类型 2 自定义类型 1 new的原理 2 delete的原理 3 new T[N]的原理 4 delete[]的原理 七 定位new表达式(placement-new) 八 …

【Android Studio】各个版本下载地址

下载地址: https://developer.android.com/studio/archive?hlzh-cn

HashMap扩容机制详解

目录 1. 扩容的触发条件 2. 扩容的具体步骤 2.1 计算新的容量 2.2 创建新的桶数组 2.3 将元素重新分配到新的桶数组中 2.4 更新容量和阈值 3. 与并发性能的关系 4. 扩容的性能优化 5. 总结 HashMap是Java中常用的数据结构之一,用于存储键值对。在HashMap内…

系列十、存储引擎

一、存储引擎 1.1、概述 大家可能没有听说过存储引擎,但是一定听过引擎这个词,引擎就是发动机,是一个机器的核心组件。 比如,对于舰载机、直升机、火箭来说,它们都有各自的引擎,引擎是它们最为核心的组件。…

RHEL8_Linux_Ansible常用模块的使用

本章主要介绍Ansible中最常见模块的使用 shell模块文件管理模块软件包管理模块服务管理模块磁盘管理模块用户管理模块防火墙管理模块 ansible的基本用法如下。 ansible 机器名 -m 模块x -a "模块的参数" 对被管理机器执行不同的操作,只需要调用不同的模块…

Pipelined-ADC设计一:序言

现在是2023年12月18日,准备开新帖,设计一个 流水线型 模数转换器( Pipelined-ADC )。记录帖,后续会放在咸鱼。同步记录,谨防盗用。 初定指标:12位50Mhz,采用2.5bit每级结构&#xff…

Goland如何进行Debug断点调试

1. 进入编辑 2. 进行编辑 3. 调试运行 将鼠标移到按钮上,即显示其功能与快捷键 4. 常用调试快捷键 按键说明F7单步执行(进入方法)F8单步执行(不进入方法)F9继续执行

如何实现TensorFlow自定义算子?

在上一篇文章中 Embedding压缩之基于二进制码的Hash Embedding,提供了二进制码的tensorflow算子源码,那就顺便来讲下tensorflow自定义算子的完整实现过程。 前言 制作过程基于tensorflow官方的custom-op仓库以及官网教程,并且在Ubuntu和Mac…

算法:单链表反转

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 一、问题描述 二、栈解法Stack 三、三指针法 总结 提示:以下是本篇文章正文内容,下面案例可供参考 一、问题描述 有个单链表,现…

【Qt之Quick模块】1. 概述及Quick应用程序创建流程

概述 Qt的Quick模块是用于创建现代化、动态和响应式用户界面的工具集。它是基于QML(Qt Meta-Object Language)和JavaScript的。 QML是一种声明性的语言,用于描述用户界面的结构和行为。它使用层叠样式表(CSS)的语法来…

创建型模式之简单工厂模式

一、概述 (1)简单工厂模式并不是一个标准的设计模式,但是它太常用了,简单而又神奇 (2)在简单工厂模式中用于创建实例的方法通常是静态方法,因此又被称为静态工厂方法模式 (3)要点:如果需要什么,只需传入一个正确的参…

鞋帽箱包品牌网站作用如何

鞋帽箱包是市场中很常见的产品,同时需求度又很高,是人们生活所需,除了个别高端品牌外,其它多数产品价格一般都比较低,因此很少有人会在意品牌,只要质量、价格、舒适度、美观好即可。 然而对企业来讲&#…

滑动窗口(一)

滑动窗口 什么是滑动窗口算法?通俗的来讲就是 “同向双指针” ,当一组数据的规律含有单调性的时候,就可以使用下面这套逻辑来优化暴力解法。 当两个指针同向移动的时候,类似于一个窗口在滑动。使用于在连续序列里找特殊的子串、…

计算机网络基础——网线认识与制作,线缆类型、线序、端接标准及注意事项

一、引言 网线制作是网络基础知识中不可或缺的。网络传输过程中,网线的质量和制作方法都会直接影响传输的速度和稳定性。本文将详细介绍网线制作的基础知识、线缆类型、线序、端接标准及注意事项。希望通过本文,读者能够更好地了解和掌握网线制作的方法…

PIG框架学习1——密码模式登录认证获取Token流程

文章目录 O、前言一、总流程概括:二、具体流程分析PIG提供的具体流程图:鉴权请求报文示例0、网关前置处理1、客户端认证处理2、正式接受登录请求3、组装认证对象4、认证管理器进行认证(授权认证调用)5、认证成功处理器 O、前言 对…

5G/4G工业无线通信模块:实现智能制造的关键利器

工业无线通信模块,作为实现智能制造的关键利器,正在推动着工业界的变革与创新。随着信息技术的快速发展和工业自动化的不断深入,工业无线通信模块正逐渐成为工业生产中不可或缺的重要组成部分。它不仅在工业自动化领域发挥着关键作用&#xf…

C# 使用FluentHttpClient请求WebApi

写在前面 FluentHttpClient 是一个REST API 异步调用 HTTP 客户端,调用过程非常便捷,采用流式编程,可以将所有请求所需的参数一次性发送,并直接获取序列化后的结果。 老规矩从NuGet上安装该类库: 这边一定要认准是 P…

科技云报道:至简至强,新一代服务器的算力美学

科技云报道原创。 在这个时代,数据和计算的边界正在迅速扩张。 随着云计算、物联网和人工智能的日益成熟,对算力的需求已经突破了传统的限制,进入了一个全新的阶段。在这个阶段,不仅是算力的量级发生了变化,其性质和…

计网02-计算机网络参考模型

一、OSI七层参考模型 1、分层的思想 分层模型用于网络协议的设计方法,本质是将网络节点间复杂的通信问题分成若干简单的问题逐一解决,通过网络的层次去找问题,将复杂问题简单化。 2、OSI参考模型 由于早期计算机厂商使用的是私有的网络模…

图书管理系统jsp + servlet+mysql

图书管理系统 项目使用jsp servletmysql实现; 登陆注册 首页 首页显示图书信息 图书管理 1添加书籍 2查询书籍 3预览书籍 4修改书籍 用户管理 1查询用户 2修改用户 3 删除用户 链接:https://pan.baidu.com/s/1QXK--ypb6OadbmKFlc0jUQ