cannot be resolved to absolute file path because it does not reside in the file system 问题解决

这篇具有很好参考价值的文章主要介绍了cannot be resolved to absolute file path because it does not reside in the file system 问题解决。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

https://cloud.tencent.com/developer/article/2193203

项目场景:

在Springboot中利用Resource来获取文件并在前端返回该文件, 本地测试正常, 打包到远程报错: cannot be resolved to absolute file path because it does not reside in the file system


问题描述:

紧接上一个问题: 项目打包成 jar 后包无法读取src/main/resources下文件, 在Springboot打包之后, 无法读取到jar包内的文件, 因此采取Resource来获取jar内相对路径地址的文件. 只有一个需要下载文件的时候没有问题, 然后在指定文件夹下新增一个文件后本地下载正常, 打包后下载出现问题: 下载该文件时, 后端抛出异常, 异常如下

class path resource [static/xxx模板.xlsx] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/mis-project-java-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!/static/%e5%b7%a5%e8%b5%84%e8%a1%a8%e6%a8%a1%e6%9d%bf.xlsx

复制


原因分析:

需要下载文件存放的地址:

cannot be resolved to absolute file path because it does not reside in the file system 问题解决

修改前代码:

    @Override
    @SneakyThrows(IOException.class)
    public HttpServletResponse downloadFile(HttpServletRequest request, HttpServletResponse response) {
        //设置文件路径
        org.springframework.core.io.Resource resource = new ClassPathResource("static/" + "xxx模板.xlsx");
        if (resource.exists()) {
            //异常在下一行抛出
            File file = resource.getFile();
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/vnd.ms-excel");
            String fileName = resource.getURI().toString().substring(resource.getURI().toString().lastIndexOf("/") + 1);
            response.setHeader("content-disposition", "attachment;filename=" + fileName);
            response.flushBuffer();
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
            OutputStream os = response.getOutputStream();
            byte[] buffer = new byte[1024];
            int i = bis.read(buffer);
            while (i != -1) {
                os.write(buffer, 0, i);
                i = bis.read(buffer);
            }
            if (bis != null) {
                bis.close();
            }
            return response;
        }
        return null;
    }

复制

对问题部分本地断点调试

本地断点调试:

  1. 可以看到, 调用的是 AbstractFileResolvingResource下的getFIle 方法. 然后该方法会调用 ResourceUtils下的getFile() 方法

    cannot be resolved to absolute file path because it does not reside in the file system 问题解决

  1. 可以看到在ResourceUtils下的getFile() 方法中, 因为 resourceUrl.getProtocol() 为File, 说明该url 地址对应的资源是文件, 所以直接返回这个文件

    cannot be resolved to absolute file path because it does not reside in the file system 问题解决

  1. 后续源码如何返回这个文件可以自己继续深入

对问题部分远程断点调试:

  1. 依旧是进入 resource.getFile(); 的方法内. 因为当前 url的protocol 属性时 jar, 不是vfs, 依旧走的是ResourceUtils下的getFile() 方法
  1. 在ResourceUtils下的getFile() 方法中, 因为 resourceUrl.getProtocol() 为jar, 因此会抛出异常

    cannot be resolved to absolute file path because it does not reside in the file system 问题解决

  1. 异常抛出后被全局捕获, 然后在前端显示

cannot be resolved to absolute file path because it does not reside in the file system 问题解决


解决方案:

通过上面的调试我们可以看到, org.springframework.core.io.Resource 这个类的getFile()方法, 会自动获取构建resource对象带参构造中的url, 然后根据这个url确定该文件的类型. 因为在本地时调试时, 通过resource.getFile()获取的url类型的 protocol 属性为File, 所以可以自动生成文件; 然而在将项目打包成jar部署在服务器上时, 因为该文件是在jar里面的. 因此通过resource.getFile()获取的url类型的 protocol 属性为jar. 所以抛出该异常 cannot be resolved to absolute file path because it does not reside in the file system: 文件url.

因此, 方法有两种: 一种是直接将该文件放入服务器其他目录下而不是在jar包中. 另一种就是通过流来获取jar里面的文件. 而本人采取第二种方式, 通过输入流来读取jar内的文件, 然后通过输出流将其输出.


修改后的代码文章来源地址https://www.toymoban.com/news/detail-417311.html

@Override
@SneakyThrows(IOException.class)
public HttpServletResponse downloadFile(HttpServletRequest request, HttpServletResponse response) {
    //设置文件路径
    org.springframework.core.io.Resource resource = new ClassPathResource("static/" + "xxx模板.xlsx");
    if (resource.exists()) {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/vnd.ms-excel");
        String fileName = resource.getURI().toString().substring(resource.getURI().toString().lastIndexOf("/") + 1);
        response.setHeader("content-disposition", "attachment;filename=" + fileName);
        response.flushBuffer();
        //放弃使用直接获取文件的方式, 改成使用流的方式
        BufferedInputStream bis = new BufferedInputStream(resource.getInputStream());
        OutputStream os = response.getOutputStream();
        byte[] buffer = new byte[1024];
        int i = bis.read(buffer);
        while (i != -1) {
            os.write(buffer, 0, i);
            i = bis.read(buffer);
        }
        if (bis != null) {
            bis.close();
        }
        return response;
    }
    return null;
}

到了这里,关于cannot be resolved to absolute file path because it does not reside in the file system 问题解决的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包