You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用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.write API仅能操作文件系统中的真实文件,无法识别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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 09:41:29