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端口已打开!")
});