👨💻作者简介:全干的java博主
🎟️个人主页:无所谓^_^
ps:点赞是免费的,却可以让写博客的作者开心好几天😎
前言
我们已经完成了前端工程页面的编写,这里废话就不多说了,我们来写后端接口
项目下载:
gitee:gitee.com/wusupweilgy...
一、后端实现
1.创建工程
创建springboot工程,然后引入以下依赖即可
xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.12</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
</dependencies>
依赖说明:
- httpcore:项目中我加入了R类,统一返回结果工具类,里面用到了一些Http状态码。
- fastjson:R类需要将数据转换为json返回给前端,所以用了这个依赖
- commons-lang3:给图片起随机名字的时候用到了
arduino
RandomStringUtils.random(6, true, true);//生成6个字符的随机串
配置文件application.yml:
yaml
# 应用名称
spring:
application:
name: ImageUpload
# 应用服务 WEB 访问端口
server:
port: 8088
#TODO改成你要保存的路径
file:
upload:
path: E:\Java\springboot-vue\image\imageupload_file\
2.编写controller
接下来,在FileController中编写图片上传接口,这里的逻辑是:
- 获取服务器保存图片的路径,如果路径中文件夹不存在,就创建该文件夹
- 对参数进行校验,判断前端传过来的图片是否为空
- 不为空就循环遍历图片数组,获取图片的后缀名,再与生成的6位的随机字符串拼接在一起,存入服务器
java
@Value("${file.upload.path}")
private String fileUploadPath;
@PostMapping("/file")
public R uploadFile(@RequestParam("files") MultipartFile[] multipartFiles) throws IOException {
String parentFile = fileUploadPath;//服务器保存图片的路径
//如果父文件夹不存在,就创建
File parent = new File(parentFile);
if (!parent.getParentFile().exists()) {
parent.mkdirs();
}
if(multipartFiles == null){
return R.error("文件为空");
}
for (MultipartFile file : multipartFiles) {
String filename = file.getOriginalFilename(); //获取上传图片的文件名,包含后缀
String suffixName = filename.substring(filename.lastIndexOf("."));//图片后缀
String randomFileName = RandomStringUtils.random(6, true, true);//生成6个字符的随机串
String nowName = randomFileName + suffixName;//最后保存在服务器时的文件名
File file1 = new File(parent, nowName);
//将图片保存入服务器
file.transferTo(file1);
}
}
获取图片列表接口编写,这里给前端返回url,然后配置跨域和静态资源映射,前端就能通过这个url路径访问了
ini
@GetMapping("/filelist")
public List<String> getURL() {
String parentFile = fileUploadPath;//服务器保存图片的路径
ArrayList<String> urls = new ArrayList<>();
File file = new File(parentFile);
File[] list = file.listFiles();
if (list == null) {
return null;
}
for (File s : list) {
urls.add("http://localhost:8088/file/" + s.getName());
}
return urls;
}
3.WebMvc配置
配置了跨域和静态资源映射
kotlin
import org.springframework.beans.factory.annotation.Value;
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;
@Configuration
public class MyWebConfigurer implements WebMvcConfigurer {
@Value("${file.upload.path}")
private String fileUploadPath;
//静态资源映射
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/file/**").addResourceLocations("file:" + fileUploadPath);
}
//跨域配置
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowCredentials(true)
.allowedOrigins("http://localhost:8080")
.allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
.allowedHeaders("*");
}
}
4.其他
为了显的项目更完整一点,我加了统一结果返回类和全局异常处理类,这里粘一下具体代码
统一结果返回类:
typescript
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import org.apache.http.HttpStatus;
import java.util.HashMap;
import java.util.Map;
/**
* 返回数据
*
* @author Mark sunlightcs@gmail.com
*/
public class R extends HashMap<String, Object> {
private static final long serialVersionUID = 1L;
public R setData(Object data) {
put("data",data);
return this;
}
//利用fastjson进行反序列化
public <T> T getData(TypeReference<T> typeReference) {
Object data = get("data"); //默认是map
String jsonString = JSON.toJSONString(data);
T t = JSON.parseObject(jsonString, typeReference);
return t;
}
public R() {
put("code", HttpStatus.SC_OK);
put("msg", "success");
}
public static R error() {
return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, "未知异常,请联系管理员");
}
public static R error(String msg) {
return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, msg);
}
public static R error(int code, String msg) {
R r = new R();
r.put("code", code);
r.put("msg", msg);
return r;
}
public static R ok(String msg) {
R r = new R();
r.put("msg", msg);
return r;
}
public static R ok(Map<String, Object> map) {
R r = new R();
r.putAll(map);
return r;
}
public static R ok() {
return new R();
}
public R put(String key, Object value) {
super.put(key, value);
return this;
}
public Integer getCode() {
return (Integer) this.get("code");
}
}
全局异常处理类:
kotlin
import com.wusuowei.lgy.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.io.IOException;
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = RuntimeException.class)
public R handler(RuntimeException e){
log.error("运行时异常:---------{}"+e.getMessage());
return R.error(e.getMessage());
}
@ExceptionHandler(value = IOException.class)
public R fileHandler(RuntimeException e){
log.error("文件上传异常:---------{}"+e.getMessage());
return R.error("文件上传异常");
}
}
二、踩坑
到这,这个项目就完成了,可以运行看有没有错误(应该不会报错,毕竟我踩了很多坑了😭),如果报红的话,可以第一时间查询资料,或者来评论区跟我唠唠😉。最后再总结我遇到了哪些坑吧!
- element-ui的文件上传组件默认是一张图片请求服务器一次,所以不能用它的submit提交,需要自己封装请求
- 跨域配置里,allowedOrigins("http://localhost:8080")这个不能写成"*",因为allowedOrigins、allowCredentials一般为一对出现,如果设置了allowCredentials(true),表示允许证书,这时allowedOrigins就不能写通配符"*"了,而需要枚举出所有固定的域来告知可跨域的范围。%25E8%25BF%2599%25E4%25B8%25AA%25E4%25B8%258D%25E8%2583%25BD%25E5%2586%2599%25E6%2588%2590%2522*%2522%25EF%25BC%258C%25E5%259B%25A0%25E4%25B8%25BAallowedOrigins%25E3%2580%2581allowCredentials%25E4%25B8%2580%25E8%2588%25AC%25E4%25B8%25BA%25E4%25B8%2580%25E5%25AF%25B9%25E5%2587%25BA%25E7%258E%25B0%25EF%25BC%258C%25E5%25A6%2582%25E6%259E%259C%25E8%25AE%25BE%25E7%25BD%25AE%25E4%25BA%2586allowCredentials(true)%25EF%25BC%258C%25E8%25A1%25A8%25E7%25A4%25BA%25E5%2585%2581%25E8%25AE%25B8%25E8%25AF%2581%25E4%25B9%25A6%25EF%25BC%258C%25E8%25BF%2599%25E6%2597%25B6allowedOrigins%25E5%25B0%25B1%25E4%25B8%258D%25E8%2583%25BD%25E5%2586%2599%25E9%2580%259A%25E9%2585%258D%25E7%25AC%25A6%2522*%2522%25E4%25BA%2586%25EF%25BC%258C%25E8%2580%258C%25E9%259C%2580%25E8%25A6%2581%25E6%259E%259A%25E4%25B8%25BE%25E5%2587%25BA%25E6%2589%2580%25E6%259C%2589%25E5%259B%25BA%25E5%25AE%259A%25E7%259A%2584%25E5%259F%259F%25E6%259D%25A5%25E5%2591%258A%25E7%259F%25A5%25E5%258F%25AF%25E8%25B7%25A8%25E5%259F%259F%25E7%259A%2584%25E8%258C%2583%25E5%259B%25B4%25E3%2580%2582 "http://localhost:8080%22)%E8%BF%99%E4%B8%AA%E4%B8%8D%E8%83%BD%E5%86%99%E6%88%90%22*%22%EF%BC%8C%E5%9B%A0%E4%B8%BAallowedOrigins%E3%80%81allowCredentials%E4%B8%80%E8%88%AC%E4%B8%BA%E4%B8%80%E5%AF%B9%E5%87%BA%E7%8E%B0%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%AE%BE%E7%BD%AE%E4%BA%86allowCredentials(true)%EF%BC%8C%E8%A1%A8%E7%A4%BA%E5%85%81%E8%AE%B8%E8%AF%81%E4%B9%A6%EF%BC%8C%E8%BF%99%E6%97%B6allowedOrigins%E5%B0%B1%E4%B8%8D%E8%83%BD%E5%86%99%E9%80%9A%E9%85%8D%E7%AC%A6%22*%22%E4%BA%86%EF%BC%8C%E8%80%8C%E9%9C%80%E8%A6%81%E6%9E%9A%E4%B8%BE%E5%87%BA%E6%89%80%E6%9C%89%E5%9B%BA%E5%AE%9A%E7%9A%84%E5%9F%9F%E6%9D%A5%E5%91%8A%E7%9F%A5%E5%8F%AF%E8%B7%A8%E5%9F%9F%E7%9A%84%E8%8C%83%E5%9B%B4%E3%80%82")
- @RequestParam("/files")将请求绑定到控制器的方法参数上,建议小伙伴们看看@RequestParam、@RequestBody以及@PathVariable去区别 三者区别
小结
本文介绍了如何使用SpringBoot创建一个简单的图片上传和展示后台接口。希望本文可以帮助你进一步学习和掌握这个技术。如果这篇文章有幸帮助到你,希望读者大大们可以给作者给个三连呀😶🌫️😶🌫️😶🌫️