SpringBoot+Vue多图片上传和展示(二)

👨‍💻作者简介:全干的java博主

🎟️个人主页:无所谓^_^

ps:点赞是免费的,却可以让写博客的作者开心好几天😎


前言

上一篇:SpringBoot+Vue多图片上传和展示(一)

我们已经完成了前端工程页面的编写,这里废话就不多说了,我们来写后端接口

项目下载:

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>

依赖说明:

  1. httpcore:项目中我加入了R类,统一返回结果工具类,里面用到了一些Http状态码。
  2. fastjson:R类需要将数据转换为json返回给前端,所以用了这个依赖
  3. 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中编写图片上传接口,这里的逻辑是:

  1. 获取服务器保存图片的路径,如果路径中文件夹不存在,就创建该文件夹
  2. 对参数进行校验,判断前端传过来的图片是否为空
  3. 不为空就循环遍历图片数组,获取图片的后缀名,再与生成的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创建一个简单的图片上传和展示后台接口。希望本文可以帮助你进一步学习和掌握这个技术。如果这篇文章有幸帮助到你,希望读者大大们可以给作者给个三连呀😶‍🌫️😶‍🌫️😶‍🌫️

相关推荐
天天进步201516 分钟前
Vue+Springboot用Websocket实现协同编辑
vue.js·spring boot·websocket
草莓base28 分钟前
【手写一个spring】spring源码的简单实现--bean对象的创建
java·spring·rpc
疯狂的沙粒36 分钟前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
drebander1 小时前
使用 Java Stream 优雅实现List 转化为Map<key,Map<key,value>>
java·python·list
小镇程序员1 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
乌啼霜满天2491 小时前
Spring 与 Spring MVC 与 Spring Boot三者之间的区别与联系
java·spring boot·spring·mvc
tangliang_cn1 小时前
java入门 自定义springboot starter
java·开发语言·spring boot
程序猿阿伟1 小时前
《智能指针频繁创建销毁:程序性能的“隐形杀手”》
java·开发语言·前端
Grey_fantasy1 小时前
高级编程之结构化代码
java·spring boot·spring cloud
弗锐土豆1 小时前
工业生产安全-安全帽第二篇-用java语言看看opencv实现的目标检测使用过程
java·opencv·安全·检测·面部