求教 Java .nio.file.Paths.get 从 Linux 迁移到 Windows 时出错是什么原因

2021-04-06 13:47:20 +08:00
 laqow

Java 小白,没调试环境,参照别人项目说明用 gradle 在 windows 上 build 了一个 jar 包,运行时出现 java.nio.file.InvalidPathException: Illegal char <:> at index 11: undefined/R:/temp 错误,感觉可能是 windows 盘符路径或反斜杠的坑,问题可能在后端也可能在前端,求教最可能的原因。同样操作在 linux 上运行是没有问题的。

项目是这个 https://github.com/epam/NGB,因为没人回答 issue 来这里问问。项目大概是 tomcat 做 server,angurjs 还是啥的做的前端,用 REST 做服务。

log 里面的错误前几行是:

ERROR [06/04/2021 01:50:55][http-nio-8080-exec-9][com.epam.catgenome.controller.ExceptionHandlerAdvice] This operation has been aborted: uri=/catgenome/restapi/files;client=0:0:0:0:0:0:0:1.
java.nio.file.InvalidPathException: Illegal char <:> at index 11: undefined/R:/temp
	at sun.nio.fs.WindowsPathParser.normalize(Unknown Source)
	at sun.nio.fs.WindowsPathParser.parse(Unknown Source)
	at sun.nio.fs.WindowsPathParser.parse(Unknown Source)
	at sun.nio.fs.WindowsPath.parse(Unknown Source)
	at sun.nio.fs.WindowsFileSystem.getPath(Unknown Source)
	at java.nio.file.Paths.get(Unknown Source)
	at com.epam.catgenome.manager.FileManager.loadDirectoryContents(FileManager.java:1919)
	at com.epam.catgenome.controller.UtilsController.loadDirectoryContents(UtilsController.java:138)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)

在 chrome 里面抓到的请求是下面这个,返回是个空的 400 错误

http://127.0.0.1:58123/catgenome/restapi/files?path=R:\temp

相关文件的代码是:

com.epam.catgenome.manager.FileManager.loadDirectoryContents(FileManager.java:1919)

    /**
     * Returns contents of a directory, specified by path, to browse NGS files
     *
     * @param path a path to directory to browse
     * @return {@link List} of {@link FsDirectory}s, and {@link FsFile}, representing subdirectories and files
     * @throws IOException
     */
    public List<AbstractFsItem> loadDirectoryContents(String path) throws IOException {

        if(!StringUtils.isEmpty(path) && !Paths.get(path).startsWith(ngsDataRootPath)) { // 第 1919 行
            throw new AccessDeniedException(
                    String.format("Parameter path doesn't fall into 'ngs.data.root.path': %s", ngsDataRootPath));
        }

        if (!filesBrowsingAllowed || ngsDataRootPath.equals(FILE_SYSTEM_ROOT)) {
            throw new AccessDeniedException("Server file system browsing is not allowed");
        }

        List<File> parentDirs = new ArrayList<>();
        if (path == null) {
            parentDirs.add(new File(ngsDataRootPath));
        } else {
            parentDirs.add(new File(path));
        }

        Assert.isTrue(parentDirs.stream().allMatch(File::exists), "Specified path does not exist: " + path);
        Assert.isTrue(parentDirs.stream().allMatch(File::isDirectory), "Specified path is not a directory: " + path);

        List<AbstractFsItem> items = new ArrayList<>();

        boolean accessDenied = false;
        String fileName = "";
        String otherFileName = "";

        for (File parentDir : parentDirs) {
            if (parentDir.listFiles() == null) {
                continue;
            }

            try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(parentDir.toPath())) {
                for (Path child : dirStream) {
                    try {
                        File childFile = child.toFile();
                        if (childFile.isDirectory()) {
                            FsDirectory directory = new FsDirectory();
                            directory.setPath(childFile.getAbsolutePath());
                            if (childFile.canRead()) {
                                directory.setFileCount(countChildrenFiles(child));
                            }

                            items.add(directory);
                        } else {
                            addFsFile(items, childFile);
                        }
                    } catch (AccessDeniedException e) {
                        LOGGER.error("Access denied:", e);
                        accessDenied = true;
                        fileName = e.getFile();
                        otherFileName = e.getOtherFile();
                    }
                }

                if (items.isEmpty() && accessDenied) {
                    throw new AccessDeniedException(fileName, otherFileName, "Access denied");
                }
            }
        }

        return items;
    }

com.epam.catgenome.controller.UtilsController.loadDirectoryContents(UtilsController.java:138)

    @ResponseBody
    @RequestMapping(value = "/files", method = RequestMethod.GET)
    @ApiOperation(
        value = "Returns directory contents",
        notes = "Returns directory contents, specified by path",
        produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiResponses(
        value = {@ApiResponse(code = HTTP_STATUS_OK, message = API_STATUS_DESCRIPTION)
        })
    public Result<FilesVO> loadDirectoryContents(@RequestParam(required = false) String path)
        throws IOException {
        return Result.success(new FilesVO(fileManager.loadDirectoryContents(path), fileManager.getNgsDataRootPath())); // 第 138 行
    }
2005 次点击
所在节点    Java
6 条回复
gitdoit
2021-04-06 13:57:22 +08:00
不是很明显吗,路径前面为什么会有 undefined ?这个 undefined 应该是前端传过来的吧
borisz
2021-04-06 14:09:14 +08:00
undefined/R:/temp 这个地址有问题吧
laqow
2021-04-06 14:38:42 +08:00
@gitdoit @borisz 谢谢。前端的请求应该就这个 http://127.0.0.1:58123/catgenome/restapi/files?path=R:\temp,linux 下也是 /home/啥啥啥 的,不知道这个 undefined 是哪里来的。机子上没有调试 java 的东西,能请问应该怎样 log UtilsController.loadDirectoryContents 收到的 path 出来吗?
laqow
2021-04-06 14:47:05 +08:00
@gitdoit
@borisz
好像有点头绪了,我试试写几个请求看看能 log 出什么东西。能请问机子上没有调试 java 的东西,应该怎样 log UtilsController.loadDirectoryContents 收到的 path 出来吗?
laqow
2021-04-06 14:48:00 +08:00
好吧,可以抄代码里面的 LOGGER.error("Access denied:", e);
Githuboy
2021-04-06 15:25:34 +08:00
问题解决了吗,到底是啥原因呢

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/768358

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX