pdf文件上传下载记录

作者:家有两宝,感恩遇见日期:2025/10/31

一:上传单个pdf文件并用hash重命名及判断文件是不是已经上传过,可以参考hash图片

@PostMapping("/uploadPdfFileSingle")
public String uploadPdfFileSingle(@RequestPart("file") MultipartFile file) {
System.err.println("开始文件上传");
if (file.isEmpty()) {
System.err.println("File cannot be empty");
}
if (!"application/pdf".equals(file.getContentType())) {
System.err.println("Only PDF files are allowed");
}
try {
// 生成文件哈希可以参考图片hash'那篇文章
String fileHash = calculateFileHash(file.getInputStream());

// 处理扩展名
String originalFileName = StringUtils.cleanPath(Objects.requireNonNull(file.getOriginalFilename()));
String fileExtension = originalFileName.contains(".")
? originalFileName.substring(originalFileName.lastIndexOf("."))
: "";

// 使用哈希值作为文件名
String storedFileName = fileHash + fileExtension;

// 创建目录 pdpdf是配置文件配置的根目录
Path uploadPath = Paths.get(pgPdf).toAbsolutePath().normalize();
if (!Files.exists(uploadPath)) {
Files.createDirectories(uploadPath);
}

// 检查文件是否已存在
Path targetLocation = uploadPath.resolve(storedFileName);
if (Files.exists(targetLocation)) {
System.err.println("File is exist"); // 文件已存在
}

// 保存文件
Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
System.err.println(storedFileName);
} catch (IOException ex) {
ex.printStackTrace();
throw new RuntimeException("File storage failed");
}
}

二:对应的下载方法

@GetMapping("/downLoadPdfFileSingle")
public void downLoadPdfFileSingle(@RequestParam("fileName") String fileName, HttpServletResponse response) throws Exception {

//传的文件名就是上传时打印的文件名storedFileName
File f = new File(pgPdf+fileName);
if (!f.exists()) {
response.sendError(404, "File not found!");
return;
}
BufferedInputStream br = new BufferedInputStream(new FileInputStream(f));
byte[] buf = new byte[1024];
int len = 0;
response.reset(); // 非常重要
//下载
response.setContentType("application/x-msdownload");
response.setHeader("Content-Disposition", "attachment; filename=" + f.getName());

OutputStream out = response.getOutputStream();
while ((len = br.read(buf)) > 0)
out.write(buf, 0, len);
br.close();
out.close();
}


pdf文件上传下载记录》 是转载文章,点击查看原文


相关推荐


Redis(91)Redis的访问控制列表(ACL)是如何工作的?
Victor3562025/10/29

Redis 6.0及以上版本支持访问控制列表(ACL),这允许更细粒度地控制不同用户的权限。ACL使得可以定义多个用户,每个用户有自己的一组权限,这些权限可以控制哪些命令可以执行,哪些键可以访问等。以下是Redis ACL的详细工作原理和示例代码。 1. 基本概念 用户:Redis的每一个用户都有一个唯一的名字。 权限:每个用户可以被授予一组权限,这些权限定义了用户可以执行哪些命令和访问哪些键。 认证:用户在连接Redis时需要提供用户名和密码进行认证。 2. 配置ACL 可以在Redis配


Java Stream流两大实战陷阱:并行流Parallel误用、List转Map时重复键异常
IT橘子皮2025/10/26

在Java 8引入的Stream API极大地简化了集合操作,让函数式编程在Java世界中大放异彩。然而,在实践中发现的,Stream API并非银弹,其中隐藏着一些容易踩坑的陷阱。本文将深入分析Stream流中最常见的两大问题:并行流的误用和List转Map时的重复键异常,并提供相应的解决方案。 一、并行流(parallel)的陷阱与优化方案 1.1 问题本质分析 并行流看似是性能优化的"神器",但实践表明,盲目使用parallel()可能适得其反: // 看似高效的并行处理,实则是性能陷阱


C 语言标准库头文件 locale.h
hubenchang05152025/10/23

#C 语言标准库头文件 locale.h 请查看 C 语言标准库头文件列表 了解更多相关 API。 这个头文件提供 本地化 的相关功能,例如设置数字和货币的格式。 设置语言环境需要操作系统支持,通常需要安装语言包。 例如: sudo apt install language-pack-zh-hans # 安装中文语言包 #类型 类型标准说明lconvC89格式化详细信息 #宏 宏标准说明NULLC89空指针常量 本地化类别宏标准说明LC_ALLC89整个 C 语言环境LC_COLLATE


火狐浏览器替换js脚本
绘梨衣の沉默2025/10/22

一、概述 本教程使用火狐浏览器演示替换前端js脚本的操作步骤。 为了方便演示,教程中使用此页面作为案例进行讲解: https://www.leavescn.com/files/demos/1-snow/snow.html 这是一个使用js代码实现的展示下雪特效的页面,如下图所示: 本教程主要演示js代码的替换过程,对于功能复杂的网站,前端包含诸多js文件,需要具备一定的js基础,能够读懂源码后才能找到你需要替换的那个js文件。 二、步骤 使用火狐浏览器打开此网页,然后按下F12键打


Redis(75)Redis分布式锁的性能如何优化?
Victor3562025/10/21

优化Redis分布式锁的性能可以从多个方面入手,包括减少锁的粒度、使用Lua脚本来确保原子操作、优化网络通信、提高Redis服务器的性能,以及优化锁的实现逻辑等。以下是一些常见的性能优化方法,并结合代码进行详细解释。 1. 减少锁的粒度 锁的粒度越小,竞争的机会就越少,从而提高系统的并发性能。比如,将全局锁拆分为多个局部锁。 // 假设我们有多个资源需要加锁,可以为每个资源设置不同的锁 public class FineGrainedRedisLock { private Jedis j


为什么 .gitignore 不生效?其实你忘了用 git rm --cached!
唐青枫2025/10/20

简介 命令格式: git rm --cached <file> 意思: 从 Git 的 索引(index,暂存区) 中移除文件,但保留工作区中的实际文件。 也就是说: 文件仍然留在硬盘(工作区); 但不再被 Git 跟踪(tracked)。 <file>...:要移除的文件或目录路径。可以指定多个文件,或使用通配符(如 *.log)。 常用选项: --cached:仅从索引移除(必须使用)。 -r 或 --recursive:递归移除目录及其内容(如果指定目录)。


【XR硬件系列】破局“芯”瓶颈:深入浅出解析XR专用芯片的必然性
元宇宙_H2025/10/18

关键词:XR芯片、低延迟、六自由度(6DoF)、异构计算、R1芯片、Motion-to-Photon、功耗、Qualcomm XR 引言:从“玩具”到“工具”的鸿沟 还记得早期的VR头显吗?厚重的机身、粗糙的画面,以及那令人不悦的眩晕感。这些体验上的“硬伤”,曾让XR技术长期徘徊在主流市场的边缘。其核心瓶颈之一,就在于当时的设备大多沿用手机等移动平台的通用芯片(SoC)。 这些“全能但不专精”的芯片,无法满足XR这一“性能吞噬兽”的苛刻需求。今天,我们就来深入探讨,为什么XR的进化之


Redis(66)Redis如何实现分布式锁?
Victor3562025/10/17

Redis 提供了多种方法来实现分布式锁,确保多个进程或机器能够协调地访问共享资源。以下是详细的实现步骤和代码示例。 1. 基于 SET 命令的分布式锁 获取锁 获取锁的核心是使用 SET 命令,并带上 NX 和 EX 选项: NX(Not eXists): 仅当键不存在时才设置键。 EX(EXpire): 设置键的过期时间,防止死锁。 # 获取锁示例 SET mylock <lock_value> NX EX 10 Lua 脚本实现 为了更加原子化,可以使用 Lua 脚本: -- 获取锁


告别异常继承树:从 NopException 的设计看“组合”模式如何重塑错误处理
canonical_entropy2025/10/16

在软件开发中,异常处理是一个不可或缺的环节。长久以来,经典的面向对象思想教导我们,为不同类型的错误建立一个庞大的继承树是一种优雅的方案。例如,定义一个基础的 AppException,然后派生出 BusinessException、SystemException 等。这种基于**继承(Inheritance)**的设计模式直观且经典。时至今日,这种思想在许多开发者心中依然根深蒂固,被认为是“正统”的 OO 设计。 然而,当系统走向分布式、服务化,并需要应对复杂的国际化、多租户、定制化需求时,这个


libevent输出缓存区的数据
我梦之62025/10/14

在网络开发中,当需要在不干扰客户端正常接收数据的前提下,验证服务端输出缓冲区中待发送数据的存在性、完整性或格式正确性(如排查客户端收不到数据的故障、确认发送数据是否符合协议规范),或监控缓冲区数据堆积情况时,会用到这段基于 libevent 库的代码。 其核心功能是对客户端连接的输出缓冲区(evbuffer)进行 “非破坏性读取”—— 先通过bufferevent_get_output获取与客户端client2关联的输出缓冲区指针,再用evbuffer_get_length获取缓冲区中待发送数据

首页编辑器站点地图

Copyright © 2025 聚合阅读

License: CC BY-SA 4.0