springboot上传文件到自定义路径并查看

上传文件

最近在学习springboot的文件上传过程中遇到一些问题,后来结合一些帖子,发现一个比较方便的解决方法。

很多资料上的例子都是将文件存放在tomcat的临时文件目录之类的位置,访问时只需要在浏览器输入localhost:8080/xxx/xxx.xxx即可。但是由于某种需求,或者避免文件存在特殊位置会被误删,导致后续相关操作出错。

参考 springboot内置tomcat文件上传的坑

我们需要将文件存放在指定位置,例如:D:/file或者/home/root/file。很显然,这时使用localhost:8080/D:/file/xxx.xxx或者localhost:8080/xxx.xxx等都是无法正确访问的。

这里我是通过配置虚拟路径来解决的,例如:将/files/**映射为D:/file。配置完成后,上传文件完毕,再输入localhost:8080/files/xxx.xxx就可查看该文件了。

上传方法

首先使用一个比较简单的方法用于上传文件。

@RestController
public class FileController {

    SimpleDateFormat sdf=new SimpleDateFormat("yyyy/MM/dd/");

    @PostMapping("/upload")
    public String upload(MultipartFile file, HttpServletRequest req) {
        String realPath=req.getSession().getServletContext().getRealPath("/uploadFile/");
        String format=sdf.format(new Date());
        File folder=new File(realPath+format);
        if(!folder.isDirectory()){
            if(!folder.mkdirs()){
                return "文件夹创建失败";
            }
        }
        String oldName=file.getOriginalFilename();
        String newName= UUID.randomUUID().toString()+oldName.substring(oldName.lastIndexOf("."),oldName.length());
        try {
            file.transferTo(new File(folder,newName));
            String filePath=req.getScheme()+"://"+req.getServerName()+":"+req.getServerPort()+"/uploadFile/"+format+newName;
            return filePath;
        }catch (IOException e){
            e.printStackTrace();
        }
        return "上传失败!";
    }
}

这里面的:

String realPath=req.getSession().getServletContext().getRealPath("/uploadFile/");

是用来获取工程的绝对路径,得到的值是这种形式(示例为linux下):
/tmp/tomcat-xxx.xxxxxxxxxxxxxx.8080/uploadFile/ 后面再拼接日期2020/07/19/。文件夹创建完成后,就可以将文件写入相应位置了。

这里还要注意一下folder.mkdirs()folder.mkdir()的区别。

参考 【JAVA】mkdir和mkdirs的区别

代码中的文件名以随机生成的UUID+后缀名构成。所有操作完成后,便返回该文件的url值。

前端页面

接着,在/resources/static下写一个简单的html页面用于测试。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="file" value="请选择文件">
    <input type="submit" value="上传">
</form>
</body>
</html>

注意name的名字要和前面方法接收的MultipartFile的参数名一样,这里统一用file

运行测试

做完这些我们直接在浏览器中进入前端测试页面,看到的是这个样子:
前端页面
选择一个图片进行上传后,浏览器会接收到上传成功的图片链接:
上传成功
复制这个链接并访问,即可查看上传的图片:
查看结果

修改为自定义路径

下面我们要将文件保存的位置设在另外的地方,这里改为自己喜欢的位置/home/root/Documents/WebFiles/test/pic/。需要修改folder的路径还有返回的filePath路径。realPath这个参数已经用不上了,我们可以把它删掉。

这里要注意folder的路径,要确保那个位置你的应用是有权限进行操作的,否则会创建文件夹失败。

    @PostMapping("/upload")
    public String upload(MultipartFile file, HttpServletRequest req) {
        // 删除 String realPath=req.getSession().getServletContext().getRealPath("/uploadFile/");        
        // 省略部分内容
        File folder=new File("/home/root/Documents/WebFiles/test/pic/"+format);
        // 省略部分内容        
        try {        
            // 省略部分内容
            String filePath=req.getScheme()+"://"+req.getServerName()+":"+req.getServerPort()+"/test/pic/"+format+newName;
            return filePath;
        }catch (IOException e){
            e.printStackTrace();
        }
        return "上传失败!";
    }

通过代码不难看出,如果我们按照这里返回的路径去查看图片,肯定是出错的。这里就不进行测试了,大家可以自行尝试。

配置虚拟路径

这里采用实现WebMvcConfigurer接口并重写addResourceHandlers的方法,还有一种通过继承WebMvcConfigurerAdapter的方法,已经被废弃了。

参考
WebMvcConfigurerAdapter过时的替换方法
SpringBoot之虚拟路径配置

为了方便,示例代码直接在当前类中实现了WebMvcConfigurer接口。不知道这样算不算正规的写法,请大家谨慎参考。

我们将/files/**映射为/home/root/Documents/WebFiles/,这时,浏览器只需要输入localhost:8080/files/便可以访问/home/root/Documents/WebFiles/下的文件。

重写完方法后,前面的upload方法需要修改一下返回路径,在原路径前增加/files即可返回正确的路径.

@RestController
public class FileController implements WebMvcConfigurer{

    SimpleDateFormat sdf=new SimpleDateFormat("yyyy/MM/dd/");

    @PostMapping("/upload")
    public String upload(MultipartFile file, HttpServletRequest req) {
         // 省略部分内容      
         String filePath=req.getScheme()+"://"+req.getServerName()+":"+req.getServerPort()+"/files/test/pic/"+format+newName;
         // 省略部分内容
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/files/**").addResourceLocations("file:/home/root/Documents/WebFiles/");
        WebMvcConfigurer.super.addResourceHandlers(registry);
    }
}

最终测试

我们再次进入浏览器上传图片,得到如下链接:
得到链接
复制链接并打开,图片显示正常,这里不放全图了:
显示结果
可以看到,图片真正所在位置是位于/home/root/Documents/WebFiles/test/pic/2020/07/19即我们设置/files映射的位置+/test/pic/2020/07/19

到这里,修改基本完成了,最后放上修改完成后的完整代码:

@RestController
public class FileController implements WebMvcConfigurer{

    SimpleDateFormat sdf=new SimpleDateFormat("yyyy/MM/dd/");

    @PostMapping("/upload")
    public String upload(MultipartFile file, HttpServletRequest req) {
        String format=sdf.format(new Date());
        File folder=new File("/home/root/Documents/WebFiles/test/pic/"+format);
        if(!folder.isDirectory()){
            if(!folder.mkdirs()){
                return "文件夹创建失败";
            }
        }
        System.out.println(folder.getPath());
        String oldName=file.getOriginalFilename();
        String newName= UUID.randomUUID().toString()+oldName.substring(oldName.lastIndexOf("."),oldName.length());
        try {
            file.transferTo(new File(folder,newName));
            String filePath=req.getScheme()+"://"+req.getServerName()+":"+req.getServerPort()+"/files/test/pic/"+format+newName;
            return filePath;
        }catch (IOException e){
            e.printStackTrace();
        }
        return "上传失败!";
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/files/**").addResourceLocations("file:/home/root/Documents/WebFiles/");
        WebMvcConfigurer.super.addResourceHandlers(registry);
    }
}
  • 14
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值