字符串形式的资源文件路径(不是流式传输)

Resource File Path as String (not streaming)

我不明白 - 我正在尝试获取文件的路径,以便可以将文件(图像)作为附件包含在电子邮件中。

我的系统由两部分组成 - 一个网络应用程序和一个 jar。 (实际上是三个部分——一个包含 DAO 等的公共共享 jar)

它们都是使用 maven 构建的。 它们都在此路径中包含此图像:

src/main/resources/logo_48.png

网络应用程序:

String logo1 = getClass().getClassLoader().getResource("logo_48.png").getPath();

这在本地 (Windows) 和 Linux

上都非常有效

Jar 应用程序:

String logo1 = getClass().getClassLoader().getResource("logo_48.png").getPath();    //doesn't work

我听取了这里的建议: How to access resources in JAR file? 这里: Reading a resource file from within jar 这里: http://www.coderanch.com/t/552720/java/java/access-text-file-JAR

及其他

大多数答案都提供将文件加载为流等,但我只希望获得分配给字符串的路径。其他资源让我破解了几个小时的代码,却发现最终结果不起作用。

在多次 /home/kalton/daily.jar!logo_48.png 不存在错误之后,我感到很沮丧,并决定采用以下解决方法:

将logo_48.png直接复制到jar所在的文件夹(/home/kalton/)

将我的 jar 应用程序代码更改为:

String logo1 = "/home/kalton/logo_48.png";

而且有效。

谁能告诉我从未解压的 JAR 中获取资源文件夹中文件的路径(作为字符串)的正确方法? 这个问题让我发疯了好几个星期! 提前致谢。 KA.

添加'path'的实际使用代码以明确使用:

public static MimeMultipart assemble4SO(String logoTop, String emailHTMLText) throws MessagingException, IOException {
    MimeMultipart content = new MimeMultipart("related");
    String cid = Long.toString(System.currentTimeMillis());
    String cidB = cid + "b";
    String cssStyle = "";

    String body = "<html><head>" + cssStyle + "</head><body><div>" + "<img src='cid:" + cid + "'/>" + emailHTMLText + "<img src='cid:" + cidB + "'/></div></body></html>";
    MimeBodyPart textPart = new MimeBodyPart();

    textPart.setContent(body, "text/html; charset=utf-8");
    content.addBodyPart(textPart);

    //add an inline image
    MimeBodyPart imagePart = new MimeBodyPart();
    imagePart.attachFile(logoTop);
    imagePart.setContentID("<" + cid + ">");
    imagePart.setDisposition(MimeBodyPart.INLINE);
    content.addBodyPart(imagePart);

..............

自上而下……

.jar 文件实际上是一个 zip 文件。 zip 文件是充当存档的单个文件。此存档中的条目不是单独的文件,它们只是 zip 文件中的压缩字节序列。它们永远不能作为单独的文件名或 File 对象访问。

同样重要:URL class getPath 方法不会 将 URL 转换为文件名.它 returns URL 的路径部分,它只是主机之后的部分(在任何查询 and/or 片段之前)。许多字符在 URL 中是非法的,需要使用百分号编码“转义”,所以如果你直接从 URL 中提取路径,你通常会得到包含百分号的东西 -转义,因此根本不是有效的文件名。

一些例子:

String path = "C:\Program Files";

URL url = new File(path).toURI().toURL();
System.out.println(url);            // prints file:/C:/Program%20Files
System.out.println(url.getPath());  // prints /C:/Program%20Files

File file = new File(url.getPath());
System.out.println(file.exists());  // prints false, because
                                    // "Program%20Files" ≠ "Program Files"

String path = "C:\Users\VGR\Documents\résumé.txt";

URL url = new File(path).toURI().toURL();

// Prints file:/C:/Users/VGR/Documents/r%C3%A9sum%C3%A9.txt
System.out.println(url);

// Prints /C:/Users/VGR/Documents/r%C3%A9sum%C3%A9.txt
System.out.println(url.getPath());

File file = new File(url.getPath());
System.out.println(file.exists());  // prints false, because
                                    // "r%C3%A9sum%C3%A9.txt" ≠ "résumé.txt"

根据您的编辑,我发现您需要字符串的真正原因是您可以调用 MimeBodyPart.attachFile。您有两个选择:

  1. 自己完成attachFile的工作:

    URL logo = getClass().getLoader().getResource("logo_48.png");
    imagePart.setDataHandler(new DataHandler(logo));
    imagePart.setDisposition(Part.ATTACHMENT);
    
  2. 将资源复制到临时文件,然后传递该文件:

    Path logoFile = Files.createTempFile("logo", ".png");
    try (InputStream stream =
        getClass().getLoader().getResourceAsStream("logo_48.png")) {
    
        Files.copy(stream, logoFile, StandardCopyOption.REPLACE_EXISTING);
    }
    imagePart.attachFile(logoFile.toFile());
    

如您所见,第一个选项更容易。第二个选项也需要清理您的临时文件,但在您发送消息之前您不想这样做,这可能需要使用 TransportListener。