图片上传问题

提到图片上传我首先想到的是:图片文件传到后端时,获取后端项目部署路径,然后在路径下创建目录并将图片放入其中(如下):

String path = request.getSession().getServletContext().getRealPath("/upload");

然后存入数据库和返回前端的url是如下形式:

String url="http://localhost:8080/blog/upload/"+newFileName;

上述这种方法是将图片文件存入后端项目的目录内,具体是在tomcat部署后端项目的目录下(作为新手我的springboot项目只会使用内嵌的tomcat,没有尝试过其他服务器),这个目录就和tomcat设置有关,很难自己定制化决定存到哪里,而且最重要的一点就是重启项目后图片全部消失了,因为tomcat每次部署都会把之前在此处已经部署的项目清理掉,再重新部署新项目。这样后端把数据库里的url返回前端,前端拿着url来请求资源,发现根本就没有想要的资源。

解决方法

后端controller:

@PostMapping("/uploadAvatar")
public AjaxResult uploadAvatar(@RequestParam("avatarFile") MultipartFile avatarFile) throws IOException {
    String uploadPath = UploadFileUtils.uploadImage("D:/mySystem/uploadPath", avatarFile);
}

UploadFileUtils是我自己写的文件上传工具类,uploadImage方法里的逻辑就是把图片文件下来到D盘的mySystem/uploadPath目录下,下载后返回url:

public class UploadFileUtils {

    public static final String IMAGE_PNG = "image/png";

    public static final String IMAGE_JPG = "image/jpg";

    public static final String IMAGE_JPEG = "image/jpeg";

    public static final String IMAGE_BMP = "image/bmp";

    public static final String IMAGE_GIF = "image/gif";

    public static String uploadImage(String path, MultipartFile file) throws IOException {
        File filePath = new File(path+"/avatar"); // 这里我又加了一层目录
        if (!filePath.exists()){
            filePath.mkdirs();
        }

        //获取文件后缀
        String extension = getExtension(Objects.requireNonNull(file.getContentType()));

        //设置新文件名
        String newFileName=UUID.randomUUID().toString().replace("-","")+"."+extension;

        File targetFile = new File(filePath, newFileName);

        file.transferTo(targetFile);

        return "/profile/avatar/"+newFileName;
    }

    public static String getExtension(String prefix)
    {
        switch (prefix)
        {
            case IMAGE_PNG:
                return "png";
            case IMAGE_JPG:
                return "jpg";
            case IMAGE_JPEG:
                return "jpeg";
            case IMAGE_BMP:
                return "bmp";
            case IMAGE_GIF:
                return "gif";
            default:
                return "";
        }
    }

}

这里返回的url并不是以http开头的,而是这样的:

/profile/avatar/4b4019b69d1840a4989bc4c19ad431bf.jpeg

而实际在磁盘中的存储路径为D:/mySystem/uploadPath/avatar/4b4019b69d1840a4989bc4c19ad431bf.jpeg,这两个路径中/avatar前边的部分是不同的,为什么要在url前边加个/profile稍后会解答。前端拿到url后基于前端项目配置有两种处理方法:

  1. 若前端配置了代理,则加上代理前缀(如/dev-api)后将此url放入img标签的src属性中,<img src="/dev-api/profile/avatar/4b4019b69d1840a4989bc4c19ad431bf.jpeg"></img>,当页面加载图片时会向http:/前端ip:前端port//dev-api/profile/avatar/4b4019b69d1840a4989bc4c19ad431bf.jpeg发送请求,这个请求会被代理转发,向后端http:/后端ip:后端port/profile/avatar/4b4019b69d1840a4989bc4c19ad431bf.jpeg发送请求。
  2. 若前端没有配置代理,则将url拼接上http:/后端ip:后端port放入img标签内,<img src="http:/后端ip:后端port/profile/avatar/4b4019b69d1840a4989bc4c19ad431bf.jpeg"></img>这时图片加载会直接向后端发送请求

以上两种方法,不论怎么处理目的都是让图片加载时向后端发送请求,请求路径为http:/后端ip:后端port/profile/avatar/4b4019b69d1840a4989bc4c19ad431bf.jpeg

然后就需要配置本篇的主角,向springboot中添加资源处理器

@Configuration
public class ResourcesConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry)
    {
        //本地文件上传路径
        registry.addResourceHandler("/profile" + "/**")
                .addResourceLocations("file:" + "D:/mySystem/uploadPath/");

    }
}

配置了这个后,所有以profile为前缀(去掉ip和端口)的请求,后端服务器都会去到指定的D:/mySystem/uploadPath/磁盘目录下找资源,以上边的请求为例,把请求路径中的/profile替换为D:/mySystem/uploadPath,后端服务器就会拿到如下资源给前端D:/mySystem/uploadPath/avatar/4b4019b69d1840a4989bc4c19ad431bf.jpeg。

总结起来就是向请求路径中添加一个虚拟路径,比如这里的/profile,然后把这个虚拟路径配置到spring boot中,配置对应的磁盘路径

Logo

前往低代码交流专区

更多推荐