我正在使用jar文件运行spring boot应用程序。
此应用程序发送带有附件的邮件。附件是jar文件的一部分。我正在使用下面的代码来获取附件。我已引用此链接Classpath resource not found when running as jar
public boolean sendEmail(String content, String subject, String from, String to, String cc, boolean isAttach, List<String> attachFiles, Session session) {
try {
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(from, "XXX"));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
if(cc!=null && !cc.equals("")) {
message.setRecipients(Message.RecipientType.CC, InternetAddress.parse(cc));
}
message.setSubject(subject);
MimeBodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setContent(content, "text/html; charset=utf8");
// creates multipart
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(messageBodyPart);
if (isAttach) {
// adds attachments
if (!attachFiles.isEmpty()) {
for (String filePath : attachFiles) {
try {
ClassPathResource classPathResource = new ClassPathResource("Brochure.pdf");
InputStream inputStream = classPathResource.getInputStream();
MimeBodyPart attachPart = new MimeBodyPart();
attachPart.attachFile(IOUtils.toString(inputStream));
multipart.addBodyPart(attachPart);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
// sets the multipart as email's content
message.setContent(multipart);
Transport.send(message);
System.out.println("sent email for " + to);
return true;
} catch (MessagingException | UnsupportedEncodingException e) {
System.out.println("email sending failed for " + to);
e.printStackTrace();
// throw new RuntimeException(e);
return false;
}
}
我正在使用getInputStream()
函数本身来搜索jar文件中的文件。但出现以下错误:
javax.mail.MessagingException: IOException while sending message;
nested exception is:
java.io.FileNotFoundException: Invalid file path
at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1365)
at javax.mail.Transport.send0(Transport.java:255)
at javax.mail.Transport.send(Transport.java:124)
at com.inversation.app.integration.service.mail.clients.GenericMailClient.sendEmail(GenericMailClient.java:95)
at com.inversation.app.jobs.CronJob.executeInternal(CronJob.java:62)
at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:75)
at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)
Caused by: java.io.FileNotFoundException: Invalid file path
at java.base/java.io.FileInputStream.<init>(FileInputStream.java:152)
at javax.activation.FileDataSource.getInputStream(FileDataSource.java:110)
at javax.activation.DataHandler.writeTo(DataHandler.java:318)
at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:1694)
at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:996)
at javax.mail.internet.MimeMultipart.writeTo(MimeMultipart.java:561)
at com.sun.mail.handlers.multipart_mixed.writeTo(multipart_mixed.java:84)
at javax.activation.ObjectDataContentHandler.writeTo(DataHandler.java:901)
at javax.activation.DataHandler.writeTo(DataHandler.java:330)
at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:1694)
at javax.mail.internet.MimeMessage.writeTo(MimeMessage.java:1913)
at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1315)
... 7 more
在这里提出这个问题之前,我已经做过研究,但是仍然无法解决问题。任何帮助,将不胜感激。
我可以使用以下代码解决问题。希望它能帮助别人。请参阅此问题-Similar issue
attachPart.setDataHandler(new DataHandler(new ByteArrayDataSource(this.getClass().getResourceAsStream("/"+filePath),"application/pdf")));
答案 0 :(得分:0)
(警告:您正在对"Brochure.pdf"
进行硬编码,并且在循环中完全忽略了filePath
。我假设您要附加filePath
的每个值。)
在the documentation for the attachFile method中可以看到,String参数必须是有效的文件名。
将InputStream中的字节转换为String当然不会产生文件名。
.jar中的资源不是文件。它是.jar文件的一部分,而不是单独的文件。
您需要手动设置MimeBodyPart的内容和文件名,而不是使用attachFile:
URL content = GenericMailClient.class.getResource("/" + filePath);
attachPart.setDataHandler(new DataHandler(content));
URI uri = content.toURI();
String path = uri.getPath();
String fileName = path.substring(path.lastIndexOf('/') + 1);
attachPart.setDisposition(Part.ATTACHMENT);
attachPath.setFileName(fileName);
(请勿尝试使用URL的getFile()方法。getFile()方法将 not 返回有效的文件名,两者都是因为URL不会t是file:
URL,因为不允许直接出现在URL中的字符(如空格)将被转义,而URI类则正确地解析URI组件并返回其未转义的形式。 )
答案 1 :(得分:-1)
我猜,您需要使用spring ResourceUtils从spring boot应用程序的类路径中更改读取文件的方式,
File file = ResourceUtils.getFile("classpath:Brochure.pdf");
InputStream in = new FileInputStream(file);
我敢肯定,它将为您服务
答案 2 :(得分:-1)
我在项目中使用了以下代码。基本上,如果没有确切的路径,我要做的是扫描整个类路径以查找所需的文件。这是为了帮助我确保不需要将文件放在特定的路径中。
这是因为使用此行时遇到与您相同的错误。
getClass().getClassLoader().getResource("Brochure.pdf")
因此,我创建了两个函数,它们使用文件名,然后将jar中的类路径包括在内,然后递归搜索文件。
private static File findConfigFile(String paths, String configFilename) {
for (String p : paths.split(File.pathSeparator)) {
File result = findConfigFile(new File(p), configFilename);
if (result != null) {
return result;
}
}
return null;
}
private static File findConfigFile(File path, String configFilename) {
if (path.isDirectory()) {
String[] subPaths = path.list();
if (subPaths == null) {
return null;
}
for (String sp : subPaths) {
File subPath = new File(path.getAbsoluteFile() + "/" + sp);
File result = findConfigFile(subPath, configFilename);
if (result != null && result.getName().equalsIgnoreCase(configFilename)) {
return result;
}
}
return null;
} else {
File file = path;
if (file.getName().equalsIgnoreCase(configFilename)) {
return file;
}
return null;
}
}
这是我的代码示例:
import java.io.File;
public class FindResourcesRecursive {
public File findConfigFile(String paths, String configFilename) {
for (String p : paths.split(File.pathSeparator)) {
File result = findConfigFile(new File(p), configFilename);
if (result != null) {
return result;
}
}
return null;
}
private File findConfigFile(File path, String configFilename) {
if (path.isDirectory()) {
String[] subPaths = path.list();
if (subPaths == null) {
return null;
}
for (String sp : subPaths) {
File subPath = new File(path.getAbsoluteFile() + "/" + sp);
File result = findConfigFile(subPath, configFilename);
if (result != null && result.getName().equalsIgnoreCase(configFilename)) {
return result;
}
}
return null;
} else {
File file = path;
if (file.getName().equalsIgnoreCase(configFilename)) {
return file;
}
return null;
}
}
}
在这里,我有一个测试用例,在我的test / resources文件夹中有一个文件“ test.txt”。该文件的内容为:
A sample file
现在,这是我的测试用例:
import org.junit.Test;
import java.io.*;
import static org.junit.Assert.fail;
public class FindResourcesRecursiveTest {
@Test
public void testFindFile() {
// Here in the test resources I have a file "test.txt"
// Inside it is a string "A sample file"
// My Unit Test will use the class FindResourcesRecursive to find the file and print out the results.
File testFile = new FindResourcesRecursive().findConfigFile(
System.getProperty("java.class.path"),
"test.txt"
);
try (FileInputStream is = new FileInputStream(testFile)) {
int i;
while ((i = is.read()) != -1) {
System.out.print((char) i);
}
System.out.println();
} catch (IOException e) {
fail();
}
}
}
现在,如果您运行此测试,它将打印出“示例文件”,并且测试将变为绿色。
现在,你还好吗?