调用Files.write抛NoSuchFileException:文件存在仍报错的Linux环境求助
java.nio.file.NoSuchFileException 处理:JAR内部路径无法写入的问题
问题场景
调用Files.write(Path.of(fileForDocumentContent.getAbsolutePath()), htmlDocument.getContent())时,Linux部署环境抛出NoSuchFileException,但本地运行正常。报错路径显示为ile:/usr/src/pok-document-service.jar!/BOOT-INF/classes!/5b1138f8-1805-4db8-a5ed-acab8509adc4.html,可见路径指向了JAR包内部的资源。
核心原因
- JAR包是只读归档文件,无法直接向其中写入内容
Files.writeAPI仅能操作文件系统中的真实文件,无法识别JAR内部的资源路径- 本地运行时,资源文件处于未打包的文件系统目录(如IDE的classes目录),因此可正常写入;部署后打包成JAR,路径变为JAR内部的资源路径,导致无法访问
解决方案
放弃向JAR内部路径写入,改用系统临时目录存储转换用的临时文件,动态生成可写的文件系统路径:
修改后的代码示例
@Override public Document convert(Document document, DocumentFormat documentFormat) { Document htmlDocument = htmlDocumentConverter.convert(document, documentFormat); File fileForDocumentContent = null; File fileForConvertedContent = null; try { log.info("Converting document from {} to {}", getSourceFormat().toString(), getTargetFormat().toString()); CalibreConfigData calibreData = calibreConfig.getConfigurationData(CalibreConversion.HTML_TO_DOCX); // 获取系统临时目录,生成临时文件 String tempDir = System.getProperty("java.io.tmpdir"); fileForDocumentContent = File.createTempFile("conversion-source-", ".html", new File(tempDir)); fileForConvertedContent = new File(tempDir, "conversion-target-" + UUID.randomUUID() + ".docx"); Files.write(fileForDocumentContent.toPath(), htmlDocument.getContent()); // 替换Calibre命令中的路径参数为临时文件的真实路径 String calibreCommand = String.format(calibreData.getCalibreCommand(), fileForDocumentContent.getAbsolutePath(), fileForConvertedContent.getAbsolutePath()); Runtime.getRuntime().exec(calibreCommand).waitFor(); byte[] convertedFileAsBytes = Files.readAllBytes(fileForConvertedContent.toPath()); return new Document(convertedFileAsBytes); } catch (InterruptedException | IOException e) { log.error("Conversion failed due to problem: " + e); throw new MetanormaConversionException("Conversion failed due to problem: " + e); } finally { deleteFilesIfPresent(fileForDocumentContent, fileForConvertedContent); } }
额外注意事项
- 需调整Calibre配置中的命令模板,将源文件、目标文件路径改为占位符(如
%s),方便动态替换为临时文件路径 - 确认Linux环境下临时目录的读写权限,确保应用拥有写入权限
- 临时文件会在finally块中删除,避免磁盘资源占用
内容的提问来源于stack exchange,提问作者me_how
相关产品推荐
相关产品推荐

