Springboot的文件上传与下载

news2024/12/27 9:06:16

Springboot的文件上传与下载

    • 文章说明
    • 配置路径映射
    • 实体类、服务与控制器
    • 前端页面
    • 前端服务器搭建

文章说明

文件上传实现了,文件下载是非常简单的,只需要通过浏览器即可下载成功;于是就没有实现专门的接口

配置路径映射

通过 public void addResourceHandlers(ResourceHandlerRegistry registry) 实现路径映射

PathConfig.java (配置常量类)

package com.boot.config;

import org.springframework.stereotype.Component;

/**
 * @author bbyh
 * @date 2022/10/29 0029 17:04
 * @description
 */
@Component
public class PathConfig {
    public static final String REQUEST_PATH = "/static/img/**";
    public static final String SYSTEM_ERROR_MSG = "暂时不支持Windows、Linux系统外的操作系统";

    public static final String WINDOWS_LOCAL_PATH = "D:/static/img/";
    public static final String LINUX_LOCAL_PATH = "/usr/local/static/img/";

    private static final String LOCAL_BASE_URL = "http://127.0.0.1:";
    private static final String REMOTE_BASE_URL = "http://47.97.170.172:";
    public static final String LOCAL_FILE_IP = LOCAL_BASE_URL + "10001";
    public static final String REMOTE_FILE_IP = REMOTE_BASE_URL + "10001";
    public static final String LOCAL_API_IP = LOCAL_BASE_URL + "8081";
    public static final String REMOTE_API_IP = REMOTE_BASE_URL + "8081";
    public static final String LOCAL_FILE_URL = LOCAL_FILE_IP + "/static/img/";
    public static final String REMOTE_FILE_URL = REMOTE_FILE_IP + "/static/img/";

    public static Boolean judgeWindows() {
        return System.getProperty("os.name").toLowerCase().contains("windows");
    }

    public static Boolean judgeLinux() {
        return System.getProperty("os.name").toLowerCase().contains("linux");
    }
}

WebConfig.java (分系统来配置了路径映射,以及对请求的IP,及请求类型进行了限定)

package com.boot.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.io.File;

import static com.boot.config.PathConfig.*;

/**
 * @author bbyh
 * @date 2022/10/28 0028 19:00
 */
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        File localDir;
        boolean flag = false;
        if (judgeWindows()) {
            localDir = new File(WINDOWS_LOCAL_PATH);
            if (!localDir.exists()) {
                flag = localDir.mkdirs();
            }
            if (flag) {
                System.out.println("已成功创建资源 " + WINDOWS_LOCAL_PATH + " 目录: ");
            }
        } else if (judgeLinux()) {
            localDir = new File(LINUX_LOCAL_PATH);
            if (!localDir.exists()) {
                flag = localDir.mkdirs();
            }
            if (flag) {
                System.out.println("已成功创建资源 " + LINUX_LOCAL_PATH + " 目录: ");
            }
        } else {
            throw new UnsupportedOperationException(SYSTEM_ERROR_MSG);
        }

        registry.addResourceHandler(REQUEST_PATH)
                .addResourceLocations("file:" + localDir.getAbsolutePath() + File.separator);
    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        if (judgeWindows()) {
            registry.addMapping("/**")
                    .allowedOrigins(LOCAL_API_IP)
                    .allowedMethods("GET", "POST", "DELETE", "PUT")
                    .maxAge(3600);
        } else if (judgeLinux()) {
            registry.addMapping("/**")
                    .allowedOrigins(REMOTE_API_IP)
                    .allowedMethods("GET", "POST", "DELETE", "PUT")
                    .maxAge(3600);
        } else {
            throw new UnsupportedOperationException(SYSTEM_ERROR_MSG);
        }
    }
}

实体类、服务与控制器

Result.java (用于返回结果)

package com.boot.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author bbyh
 * @date 2022/10/27 0027 19:17
 * @description
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Result {
    public static final String SUCCESS = "200";
    public static final String ERROR = "500";

    private Object data;
    private String msg;
    private String code;

    public static Result success(Object data, String msg) {
        return new Result(data, msg, SUCCESS);
    }

    public static Result error(Object data, String msg) {
        return new Result(data, msg, ERROR);
    }
}

实现服务类

package com.boot.service;

import com.boot.entity.Result;
import org.springframework.web.multipart.MultipartFile;

/**
 * @author bbyh
 * @date 2022/10/4 0004 16:40
 * @description
 */
public interface FileService {
    /**
     * 处理上传的文件
     *
     * @param file    所上传文件
     * @param isLocal 是否是本地环境
     * @return 返回上传文件放到目录后的路径,最终将URL返回到前端页面,随着文章保存到数据库中
     */
    Result upload(MultipartFile file, Boolean isLocal);
}
package com.boot.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.json.JSONObject;
import com.boot.entity.Result;
import com.boot.service.FileService;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;

import static com.boot.config.PathConfig.*;

/**
 * @author bbyh
 * @date 2022/10/4 0004 16:41
 * @description
 */
@Service
public class FileServiceImpl implements FileService {
    @Override
    public Result upload(MultipartFile file, Boolean isLocal) {
        String fileName = System.currentTimeMillis() + "__" + file.getOriginalFilename();
        JSONObject jsonObject = new JSONObject();
        if (isLocal) {
            try {
                FileUtil.writeBytes(file.getBytes(), WINDOWS_LOCAL_PATH + fileName);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            jsonObject.putOpt("url", LOCAL_FILE_URL + fileName);
        } else {
            try {
                FileUtil.writeBytes(file.getBytes(), LINUX_LOCAL_PATH + fileName);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            jsonObject.putOpt("url", REMOTE_FILE_URL + fileName);
        }
        jsonObject.putOpt("fileName", fileName);
        return Result.success(jsonObject, "图片上传成功");
    }
}

控制器

package com.boot.controller;

import com.boot.entity.Result;
import com.boot.service.FileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import static com.boot.config.PathConfig.*;

/**
 * @author bbyh
 * @date 2022/10/29 0029 13:53
 * @description
 */
@RestController
@RequestMapping("/file")
public class FileController {
    @Autowired
    FileService fileService;

    @PostMapping("/upload")
    public Result upload(@RequestParam MultipartFile file) {
        if (judgeWindows()) {
            return fileService.upload(file, true);
        } else if (judgeLinux()) {
            return fileService.upload(file, false);
        } else {
            throw new UnsupportedOperationException(SYSTEM_ERROR_MSG);
        }
    }
}

前端页面

采用Vue编写,结合Element-ui-plus的上传组件实现

App.vue

<template>
    <div id="app">
        <el-upload
            class="upload"
            action="#"
            :auto-upload="false"
            :on-change="handleChange"
            :limit="20"
            :show-file-list="false"
        >
            <el-image
                id="download"
                :src="avatarUrl"
                style="width: 100%; height: 100%"
            ></el-image>
        </el-upload>
    </div>
</template>

<script>
import { ref } from "@vue/reactivity";
import { postFileRequest } from "./utils/api";

export default {
    name: "App",
    components: {},
    setup() {
        let avatarUrl = ref("http://127.0.0.1:10001/static/img/10.jpg");
        function handleChange(file) {
            let formData = new FormData();
            formData.append("file", file.raw);
            postFileRequest("/file/upload", formData).then((response) => {
                avatarUrl.value = response.data.data.url;
            });
        }

        return {
            avatarUrl,
            handleChange,
        };
    },
};
</script>

<style>
* {
    padding: 0;
    margin: 0;
}
.upload {
    background-color: rgb(182, 214, 215);
    width: 30%;
    height: 30%;
}
</style>

api.js

import axios from "axios";
import { ElMessage } from 'element-plus';

const localPath = 'http://127.0.0.1:9000'
const localFilePath = 'http://127.0.0.1:10001'
const remoteFilePath = 'http://47.97.170.172:10001'

export function message(msg, type) {
    ElMessage({
        message: msg,
        showClose: true,
        type: type,
        center: true
    })
}

export const getRequest = (url, params) => {
    return axios({
        method: 'get',
        url: localPath + url,
        params: params
    })
}

export const postRequest = (url, params) => {
    return axios({
        method: 'post',
        url: localPath + url,
        data: params
    })
}

export const postFileRequest = (url, params) => {
    return axios({
        method: 'post',
        url: localFilePath + url,
        data: params
    })
}

export const putRequest = (url, params) => {
    return axios({
        method: 'put',
        url: localPath + url,
        data: params
    })
}

export const deleteRequest = (url, params) => {
    return axios({
        method: 'delete',
        url: localPath + url,
        data: params
    })
}

前端服务器搭建

server.js ,其余静态文件放在static文件夹下即可
在这里插入图片描述

const express = require('express');

const app = express();
app.use(express.static(__dirname + '/static'))

app.listen(8081, ()=>{
    console.log("服务器端8080端口已打开!")
});

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

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

相关文章

多方法做配对样本t检验(三)

Wilcoxon符号秩检验 Wilcoxon符号秩检验&#xff08;Wilcoxon Signed-Rank Test&#xff09; 是一种非参数统计方法&#xff0c;用于检验两组相关样本&#xff08;配对样本&#xff09;之间的差异是否显著。它通常用来代替配对样本t检验&#xff0c;特别是在数据不符合正态分布…

如何选择最适合企业的ETL解决方案?

在今天的大数据时代&#xff0c;企业的数据管理和处理变得愈发重要。企业也越来越依赖于数据仓库和数据湖来提取、转换和加载&#xff08;ETL&#xff09;关键业务信息。一个高效、灵活的ETL解决方案不仅能提升数据处理能力&#xff0c;还能为企业决策提供有力支持。然而&#…

前端node.js

一.什么是node.js 官网解释:Node.js 是一个开源的、跨平台的 JavaScript 运行时环境。 二.初步使用node.js 需要区分开的是node.js和javascript互通的只有console和定时器两个API. 三.Buffer Buffer 是一个类似于数组的 对象&#xff0c;用于表示固定长度的字节序列。Buffer…

Facebook的开源项目解析:推动开发者社区的技术进步

Facebook&#xff0c;作为全球领先的社交平台之一&#xff0c;其在技术领域的创新不仅体现在产品功能的实现上&#xff0c;也积极推动开源社区的发展。开源项目已经成为Facebook技术战略的重要组成部分&#xff0c;通过开源&#xff0c;Facebook不仅加速了技术进步&#xff0c;…

本地学习axios源码-如何在本地打印axios里面的信息

1. 下载axios到本地 git clone https://github.com/axios/axios.git 2. 下载react项目, 用vite按照提示命令配置一下vite react ts项目 npm create vite my-vue-app --template react 3. 下载koa, 搭建一个axios请求地址的服务端 a.初始化package.json mkdir koa-server…

电阻可靠性的内容

一、影响电阻可靠性的因素&#xff1a; 影响电阻可靠性的因素有温度系数、额定功率&#xff0c;最大工作电压、固有噪声和电压系数 &#xff08;一&#xff09;温度系数 电阻的温度系数表示当温度改变1摄氏度时&#xff0c;电阻阻值的相对变化&#xff0c;单位为ppm/℃.电阻温…

uniapp联系我们页的设计和实现

联系我们页 代码 map文档&#xff1a;map | uni-app官网 (dcloud.net.cn) <template><view class"contact"><image class"img" src"http://www.itcast.cn/2018czydz/images/gywmban.jpg"></image><view class"…

算法竞赛进阶指南——位运算

算法竞赛进阶指南——位运算 与或非异或and&#xff0c;&or&#xff0c;|not&#xff0c;~xor&#xff0c;^ 在m位二进制数中&#xff0c;通常称最低位为第0位&#xff0c;从右到左以此类推&#xff0c;最高位是第m-1位 补码&#xff1a; unsigned int&#xff1a; 直接把…

【科研】9如何高效阅读和理解学术论文

【科研】9如何高效阅读和理解学术论文 写在最前面一、为什么需要系统的阅读方法&#xff1f;二、阅读论文的11步方法三、实践示例四、常见问题解答五、结语 &#x1f308;你好呀&#xff01;我是 是Yu欸 &#x1f30c; 2024每日百字篆刻时光&#xff0c;感谢你的陪伴与支持 ~ …

Java 泛型详细解析

泛型的定义 泛型类的定义 下面定义了一个泛型类 Pair&#xff0c;它有一个泛型参数 T。 public class Pair<T> {private T start;private T end; }实际使用的时候就可以给这个 T 指定任何实际的类型&#xff0c;比如下面所示&#xff0c;就指定了实际类型为 LocalDate…

Design Linear Filters in the Frequency Domain (MATLAB帮助文档)

Design Linear Filters in the Frequency Domain 这个帮助文档写得很好&#xff0c;简单明了&#xff0c;一句废话没有。 This topic describes functions that perform filtering in the frequency domain. 2-D Finite Impulse Response (FIR) Filters The Image Processi…

手机实时提取SIM卡打电话的信令声音-蓝牙电话如何适配eSIM卡的手机

手机实时提取SIM卡打电话的信令声音 --蓝牙电话如何适配eSIM卡的手机 一、前言 蓝牙电话的海外战略中&#xff0c;由于海外智能手机市场中政策的差异性&#xff0c;对内置eSIM卡的手机进行支持是非常合理的需求。Android系列手机中&#xff0c;无论是更换通信运营商&#xf…

软通动力携子公司鸿湖万联、软通教育助阵首届鸿蒙生态大会成功举办

11月23日中国深圳&#xff0c;首届鸿蒙生态大会上&#xff0c;软通动力及软通动力子公司鸿湖万联作为全球智慧物联网联盟&#xff08;GIIC&#xff09;理事单位、鸿蒙生态服务&#xff08;深圳&#xff09;有限公司战略合作伙伴&#xff0c;联合软通教育深度参与了大会多项重磅…

【论文笔记】Frequency Domain Model Augmentation for Adversarial Attack

Abstract 对于黑盒攻击&#xff0c;替代模型与受害模型之间的差距通常较大&#xff0c;表现为较弱的攻击性能。基于对抗样本的可迁移性可以通过同时攻击不同模型来提高的观察&#xff0c;提出了利用变换图像模拟不同模型的模型增强方法。 然而&#xff0c;现有的空间域变换并没…

【人工智能-科普】深度森林:传统机器学习与深度学习的创新结合

文章目录 深度森林:传统机器学习与深度学习的创新结合一、什么是深度森林?二、深度森林的工作原理1. **特征提取和转换**2. **多层级训练**3. **最终分类**三、深度森林的关键组成部分1. **森林层(Forest Layer)**2. **级联结构(Cascade Structure)**3. **特征增强(Feat…

嵌入式硬件实战提升篇(三)商用量产电源设计方案 三路电源输入设计 电源管理 多输入供电自动管理 DCDC降压

引言&#xff1a;本文你能实际的了解到实战量产产品中电源架构设计的要求和过程&#xff0c;并且从实际实践出发搞懂电源架构系统&#xff0c;你也可以模仿此架构抄板到你自己的项目&#xff0c;并结合硬件篇之前的项目以及理论形成正真的三路电源输入设计与开发板电源架构块供…

网络——HTTP与HTTPS三次握手和四次挥手

HTTP协议本身并不直接处理TCP连接的建立和关闭&#xff0c;这些是由底层的TCP协议来完成的。但是&#xff0c;由于HTTP通常运行在TCP之上&#xff0c;因此理解TCP的三次握手&#xff08;用于建立连接&#xff09;和四次挥手&#xff08;用于关闭连接&#xff09;对于理解HTTP通…

了解Linux —— 理解其中的权限

前言 在了解Linux权限之前&#xff0c;先来探讨我们使用的shell 命令它到底是什么&#xff1f; Linux 是一个操作系统&#xff0c;我们称其为内核(kernel) &#xff0c;正常情况下&#xff0c;我们一般用户操作并不是去直接使用内核&#xff0c;而是通过kernel 的外壳程序&…

TYUT设计模式大题

对比简单工厂&#xff0c;工厂方法&#xff0c;抽象工厂模式 比较安全组合模式和透明组合模式 安全组合模式容器节点有管理子部件的方法&#xff0c;而叶子节点没有&#xff0c;防止在用户在叶子节点上调用不适当的方法&#xff0c;保证了的安全性&#xff0c;防止叶子节点暴露…

深入理解 AI 产品的核心价值——《AI产品经理手册》

现在&#xff0c;人们对AI 充满了兴趣和看法。这些年&#xff0c;我亲身经历了对AI 的感受和认识的此起彼伏。我还是学生时&#xff0c;就对AI 以及伴随而来的第四次工业革命感到无比激动和期待。然而&#xff0c;当我开始组织读书会&#xff0c;每月阅读有关AI 的书籍&#xf…