低头凝望镜中月
不如关注木丘白
一步两步向前走
共同学习一起来
这两周没写文章,主要是前几天在做一个发送pdf文件到用户邮箱的需求,再加上这段时间需求排期比较紧,马上要发版了,所以没腾出时间。今天正好抽点时间写一下发送pdf文件到邮箱遇到的问题吧。
前言
需求很简单,没有啥复杂逻辑,就是用户在APP端输入邮箱地址然后我们就把他要的单据信息生成pdf文件,以邮件的形式发送给用户,pdf添加在附件里。我们项目用的是springboot,发送带附件的邮件用JavaMailSender很好实现,这不是问题,问题就在生成pdf文件这,由于我们的管理后台也有一个下载pdf文件的功能,我就想着直接复用管理后台的接口,然后包装成附件,改吧改吧这需求分分钟就能搞定了,可惜问题就在这出现了。。。
HttpServletResponse
一般我们遇到文件下载的需求,不论是Excel还是pdf或者word,都会用到HttpServletResponse,然后把文件以流的形式返回给前端,前端获取到流之后再生成文件。HttpServletResponse提供了getOutputStream()方法,返回一个ServletOutputStream类型的输出流。
说到这里还是先上代码,看一下发送邮件的实现吧
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(发送人的邮箱,一般是公司邮箱);
helper.setTo(用户邮箱);
helper.setCc(抄送邮箱);
helper.setSubject(邮件主题);
helper.setText(邮件内容, 是否使用html格式);
FileSystemResource file = new FileSystemResource(new File(filePath));
String fileName = filePath.substring(filePath.lastIndexOf(File.separator));
//添加附件
helper.addAttachment(fileName, file);
mailSender.send(message);
看一下添加附件addAttachment这个方法,看源码,人家提供了4种添加附件的方法
看这几个参数,你会发现一个共同点,那就是inputStream,他们都需要一个输入流。
前面我说了,我想复用之前的方法,但是人家已经把数据写到outputStream里了,而我需要inputStream,相信大家肯定会想把outputStream转成inputStream,问题就在这了,问了度娘千百遍,方法无外乎三种
一、使用byte array缓存转换
二、使用Pipes
三、Circular Buffers
这里我就不详细写了,可以自己问问度娘
上面说过人家返回的是一个ServletOutputStream类型的输出流,这个玩意要转inputStream反正我是没转成。如果有哪位大神能够实现希望能够在留言里分享。
end
解决办法也很简单,最终为了降低影响范围,不改变原有的文件生成逻辑,我把原来的方法加了一个返回值OutputStream,然后使用上面的第一种转换方法
//先把outputStream强转成ByteArrayOutputStream
ByteArrayOutputStream byteArrayOutputStream = (ByteArrayOutputStream) outputStream;
//再把ByteArrayOutputStream转成ByteArrayInputStream
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
最后再把byteArrayInputStream当成参数添加到附件,大功告成。
如果有伙伴还有更好的方法或者还有什么疑问,可以在给我留言或者在留言区评论哦
![f07ce824eb547e1a1ecf4311708d9d08.png](https://i-blog.csdnimg.cn/blog_migrate/e345d65a6b255166132b1e7e99ea5b7e.png)
点在看~
![5ce5577e46f77f25c8e1d0b8e60062d3.gif](https://i-blog.csdnimg.cn/blog_migrate/6478100ca223f779cb80c1d6c34e1058.gif)
捧个人场就行~