SpringBoot上传与下载文件

使用SpringBoot的虚拟路径映射。

Config中的类

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

/**
 * 图片绝对地址与虚拟地址映射
 */

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {

    @Value("${realityFileDepositPath}")
    private String realityFileDepositPath;

    @Value("${virtualFileDepositPath}")
    private String virtualFileDepositPath;

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler(virtualFileDepositPath)
                .addResourceLocations("file:" + realityFileDepositPath);
    }
}

Control中的类

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import xin.students.service.UpdateOrDownloadService;

@RestController
public class UpdateOrDownloadController {

    @Autowired
    UpdateOrDownloadService updateOrDownloadService;

    @PostMapping("/api/upload")
    public ResponseEntity<String> handleFileUpload(@RequestParam("file") MultipartFile file) {
        return updateOrDownloadService.handleFileUpload(file);
    }

    @GetMapping("/api/upload/{fileName:.+}")
    public ResponseEntity<Resource> downloadFile(@PathVariable String fileName) {
        return updateOrDownloadService.downloadFile(fileName);
    }
}

Service中的类

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;

import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;

@Service
public class UpdateOrDownloadService {

    @Value("${virtualFileDepositPath}")
    private String virtualFileDepositPath;

    @Value("${realityFileDepositPath}")
    private String realityFileDepositPath;


    public ResponseEntity<String> handleFileUpload(@RequestParam("file") MultipartFile file) {
        // 获取文件名
        String fileName = file.getOriginalFilename();

        // 确保文件名存在并且不是.exe文件
        if (fileName != null && !fileName.toLowerCase().endsWith(".exe")) {
            fileName = System.currentTimeMillis() + fileName;
            // 检查文件大小是否合适
            if (file.getSize() <= 10 * 1024 * 1024) { // 10 MB
                // 保存文件
                try {
                    String fullPath = realityFileDepositPath + fileName;
                    file.transferTo(new File(fullPath));
                    System.out.println("Public document has been saved to: " + fullPath);
                } catch (IOException e) {
                    e.printStackTrace();
                    return new ResponseEntity<>("Public document upload failed due to internal error", HttpStatus.INTERNAL_SERVER_ERROR);
                }
                // 返回文件访问虚拟路径
                return new ResponseEntity<>(virtualFileDepositPath.substring(0, virtualFileDepositPath.length() - 2) + fileName, HttpStatus.OK);
            } else {
                return new ResponseEntity<>("Public document size exceeds 10MB", HttpStatus.BAD_REQUEST);
            }
        } else {
            // 提供一个不同的错误消息
            return new ResponseEntity<>("Public document format is not supported or is executable, which is not allowed", HttpStatus.BAD_REQUEST);
        }
    }

    public ResponseEntity<Resource> downloadFile(String fileName) {
        try {
            // 确定文件的存储路径
            Path filePath = Paths.get(realityFileDepositPath).resolve(fileName).normalize();
            Resource resource = new UrlResource(filePath.toUri());
            if(resource.exists() || resource.isReadable()) {
                // 确保文件名编码正确,避免乱码
                String encodedFileName = URLEncoder.encode(resource.getFilename(), StandardCharsets.UTF_8.toString());
                String contentDisposition = ContentDisposition.builder("attachment")
                        .filename(encodedFileName, StandardCharsets.UTF_8)
                        .build()
                        .toString();

                return ResponseEntity.ok()
                        .header(HttpHeaders.CONTENT_DISPOSITION, contentDisposition)
                        .body(resource);
            } else {
                return ResponseEntity.notFound().build();
            }
        } catch (IOException e) {
            // 如果无法读取文件,返回错误响应
            return ResponseEntity.internalServerError().build();
        }
    }
}

application.yml配置文件

virtualFileDepositPath: /api/image/**
realityFileDepositPath: D:\xinFiles\ #结束必须要带/

测试代码

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>文件上传和下载</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            flex-direction: column;
        }
        .container {
            text-align: center;
        }
        input[type="text"], input[type="file"] {
            margin: 10px 0;
        }
    </style>
    <script>
        function uploadFile() {
            var formData = new FormData();
            var fileField = document.querySelector("input[type=file]");

            formData.append('file', fileField.files[0]);

            fetch('/api/upload', {
                method: 'POST',
                body: formData
            })
                .then(response => response.text())
                .then(result => {
                    alert('上传成功: ' + result);
                })
                .catch(error => {
                    console.error('上传出错:', error);
                    alert('上传失败');
                });
        }

        function downloadFile() {
            var fileName = document.getElementById("filename").value;
            if (fileName) {
                window.open('/api/upload/' + fileName, '_blank');
            } else {
                alert('请输入文件名');
            }
        }
    </script>
</head>
<body>
<div class="container">
    <h1>文件上传</h1>
    <input type="file" id="fileInput"><br>
    <button onclick="uploadFile()">上传文件</button>

    <h1>文件下载</h1>
    <input type="text" id="filename" placeholder="请输入文件名"><br>
    <button onclick="downloadFile()">下载文件</button>
</div>
</body>
</html>

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

收单外包机构评级等级为何获D、E级及其影响分析

孟凡富 中国支付清算协会发布2022年度收单外包服务机构评级等级。本次评级工作&#xff0c;共有包括银行和非银行支付机构在内的134家收单机构对13000家外包机构进行了评价&#xff0c;参评外包机构数量较上一年度增长35.59%&#xff0c;评级工作覆盖面继续扩大。评级等级在C级…

中波发射机概述

一、简介 1.1 中波发射机简介 中波发射机是一种用于广播电台传输中波频率信号的设备。它们是广播电台系统的重要组成部分&#xff0c;用于发送声音、音乐和其他信息到广泛的地理区域。中波频率范围一般介于530kHz至1700kHz之间&#xff0c;具有较好的传播性能&#xff0c;可以…

社区街道治安智慧监管方案,AI算法赋能城市基层精细化治理

一、背景需求分析 随着城市建设进程的加快&#xff0c;城市的管理也面临越来越多的挑战。例如&#xff0c;在城市街道的管理场景中&#xff0c;机动车与非机动车违停现象频发、摊贩占道经营影响交通、街道垃圾堆积影响市容市貌等等&#xff0c;都成为社区和街道的管理难点。这…

yo!这里是STL::unordered系列简单模拟实现

目录 前言 相关概念介绍 哈希概念 哈希冲突与哈希函数 闭散列 框架 核心函数 开散列 框架 核心函数 哈希表&#xff08;开散列&#xff09;的修改 迭代器实现 细节修改 unordered系列封装 后记 前言 我们之前了解过map和set知道&#xff0c;map、set的底层结构是…

集合贴4——QA机器人设计与优化

基础课21——知识库管理-CSDN博客文章浏览阅读342次&#xff0c;点赞6次&#xff0c;收藏2次。知识库中有什么信息内容&#xff0c;决定了智能客服机器人在回答时可以调用哪些信息内容&#xff0c;甚至可以更简单地理解为这是智能客服机器人的话术库。https://blog.csdn.net/22…

Leetcode-2 两数相加

不知道为什么有些测试用例通不过&#xff0c;思路很明晰&#xff0c;改不明白了&#xff0c;求大佬指点&#xff01;&#xff01;&#xff01;&#xff01; /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNo…

写一下关于部署项目到服务器的心得(以及遇到的难处)

首先要买个服务器(本人的是以下这个) 这里我买的是宝塔面板的,没有宝塔面板的也可以自行安装 点击登录会去到以下页面 在这个界面依次执行下面命令会看到账号和密码和宝塔面板内外网地址 sudo -s bt 14点击地址就可以跳转宝塔对应的内外网页面 然后使用上述命令提供的账号密…

《006.Springboot+vue之旅游信息推荐系统》【有文档】

《006.Springbootvue之旅游信息推荐系统》【有文档】 项目简介 [1]本系统涉及到的技术主要如下&#xff1a; 推荐环境配置&#xff1a;DEA jdk1.8 Maven MySQL 前后端分离; 后台&#xff1a;SpringBootMybatis; 前台&#xff1a;vueElementUI; [2]功能模块展示&#xff1a; …

计算机是如何进行工作的+进程和线程

一)计算机是如何工作的? 指令是如何执行的?CPU基本工作过程&#xff1f; 假设上面有一些指令表&#xff0c;假设CPU上面有两个寄存器A的编号是00&#xff0c;B的编号是01 1)第一个指令0010 1010&#xff0c;这个指令的意思就是说把1010地址上面的数据给他读取到A寄存器里面 2…

数据结构-图的应用

最小生成树&#xff08;最小代价树&#xff09; 对于一个带权连通无向图G(V,E)&#xff0c;生成树不同&#xff0c;每棵树的权&#xff08;即树中所有边上的权值之和)也可能不同。设R为G的所有生成树的集合&#xff0c;若T为R中边的权值之和最小的生成树&#xff0c;则T称为G的…

商城免费搭建之java商城 java电子商务Spring Cloud+Spring Boot+mybatis+MQ+VR全景+b2b2c

1. 涉及平台 平台管理、商家端&#xff08;PC端、手机端&#xff09;、买家平台&#xff08;H5/公众号、小程序、APP端&#xff08;IOS/Android&#xff09;、微服务平台&#xff08;业务服务&#xff09; 2. 核心架构 Spring Cloud、Spring Boot、Mybatis、Redis 3. 前端框架…

工业级环网交换机:高效过滤和转发数据包的网络设备

环形网络是一种网络拓扑结构&#xff0c;其特点是将每个设备连成一个连续的环形。它可以确保一台设备发出的信号可以被环上所有其他设备接收到。环网冗余是指工业级环网交换机是否能够应对网络线缆连接中断的情况。当出现连接中断时&#xff0c;工业级环网交换机会接收到此消息…

常见排序算法之快速排序

快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法。 基本思想为∶任取待排序元素序列中的某元素作为基准值&#xff0c;按照该排序码将待排序集合分割成两子序列&#xff0c;左子序列中所有元素均小于基准值&#xff0c;右子序列中所有元素均大于基准值&#xff0c;…

【Pytest】跳过执行之@pytest.mark.skip()详解

一、skip介绍及运用 在我们自动化测试过程中&#xff0c;经常会遇到功能阻塞、功能未实现、环境等一系列外部因素问题导致的一些用例执行不了&#xff0c;这时我们就可以用到跳过skip用例&#xff0c;如果我们注释掉或删除掉&#xff0c;后面还要进行恢复操作。 1、skip跳过成…

nodejs express multer 保存文件名为中文时乱码,问题解决 originalname

nodejs express multer 保存文件名为中文时乱码&#xff0c;问题解决 originalname 一、问题描述 用 express 写了个后台&#xff0c;在接收文件并保存的时候 multer 接收到的文件名为乱码。 二、解决 找了下解决方法&#xff0c;在 github 的 multer issue 中找到了答案 参…

【MySQL进阶之路丨第十七篇(完结)】一文带你精通MySQL运算符

引言 在上一篇中我们介绍了MySQL函数&#xff1b;在开发中&#xff0c;对MySQL运算符的运用是十分重要的。这一篇我们使用命令行方式来帮助读者掌握MySQL中运算符的操作。 上一篇链接&#xff1a;【MySQL进阶之路丨第十六篇】一文带你精通MySQL函数 MySQL运算符 MySQL中的运…

node插件MongoDB(四)—— 库mongoose 的个性话读取(字段筛选、数据排序、数据截取)(四)

文章目录 一、字段筛选二、数据排序三、数据截取1. skip 跳过2. limit 限定![在这里插入图片描述](https://img-blog.csdnimg.cn/c7067b1984ee4c6686f8bbe07cae9176.png) 一、字段筛选 字段筛选&#xff1a;只读取指定的数据&#xff0c;比如集合&#xff08;表&#xff09;中有…

JMeter 相关的面试题

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;加入1000人软件测试技术学习交流群&#x1f4e2;资源分享&#xff1a;进了字节跳动之后&#xff0c;才…

【已验证】php配置连接sql server中文乱码(解决方法)更改utf-8格式

解决数据库中的中文数据在页面显示乱码的问题 在连接的$connectionInfo中设置"CharacterSet" > "UTF-8"&#xff0c;指定编码方式即可 $connectionInfo array("UID">$uid, "PWD">$pwd, "Database">$database…

提升采购订单管理效率的五个最佳实践

企业每年都要订购成千上万的商品和服务。公司运营和发展所需的一切都来自庞大的供应商网络&#xff0c;而沟通这些需求的主要方式是通过采购订单。 由于所有订单都会流经系统&#xff0c;而且每个月都会发生数千元不等的供应支出&#xff0c;因此掌握采购订单流程成为重中之重…