遇到的问题:
一、如何添加附件?
参考链接1 https://www.cnblogs.com/ysocean/p/7666061.html
参考链接2 https://blog.youkuaiyun.com/lovecuidong/article/details/92658140
二、因为是微服务项目,所以上传附件的时候,不可能是直接从本地获取,而是在各个微服务模块之间互相传递?
想到的方法:使用接口中使用@Requestbody MailInfo @RequestParam MultipartFile file
接下来又出现问题了
由于@RequestBody 的接收的Http请求Header的content-type属性为:application/json
@RequestParam MultipartFile file的接收的Http请求Header的content-type属性为:multipart/form-data
经过分析:MultipartFile这样的multipart/form-data媒体类型优先级会高于application/json,而配置@RequestBody 感觉使用一个低优先级的handle一个高优先级的从而报错。所以在multipart/form-data媒体类型请求时和@RequestBody不能共存
拿怎么解决这个冲突呢?那就只能放弃其中一个了,不过我之前又看到过设置两个请求头的方法,具体在哪我找不到了......
所以说,当我们解决一个问题的时候,这个解决方法又会带来另一种问题(需要对现有代码大改问题),那么我们应该考虑换一种解决方法!
在这里我是采用阿里云OSS对象存储,可以把文件上传到OSS上,因为OSS有提供下载文件流的API,所以我们能够在OSS下载文件流再转换成自己想要File对象,于是新的问题又出现了,在我成功实现发送带附件的邮件时,发现只有文本文件下载完之后能正常打开,这是为什么呢?
首先需要分析一下文件传输的整个过程:1.从OSS上下载ossObject 2.ossObject转File 3.file发送到客户邮箱
所以我现在第二步中直接执行保存到本地,发现非纯文本文件还是无法正常打开,那么可能存在两个原因:
1、ossObject转File的代码有问题
2、ossObject转File正常,但是需要对不用类型文件进行解析或者读取(如Excel文件利用POI的类库进行解析后再读)
以下是我的ossObject转File的代码(这里有个坑,但是我当时候没发现)
private void ossObjectToFile(OSSObject ossObject, File file) throws IOException {
InputStream inputStream = ossObject.getObjectContent();
//读取inputstream所含字节数
byte[] bytes = new byte[inputStream.available()];
//从InputStream中读出内存到byte[]中
inputStream.read(bytes);
//FileOutputStream写入文件
OutputStream outStream = new FileOutputStream(file);
outStream.write(bytes);
//关闭流
inputStream.close();
outStream.close();
}
过程: 把ossobject转换成Inputstream, 初始化一个大小为Inputstream字节数大小的字节数组,再从InputStream中读出内存到byte[]中然后,使用FileOutputStream写入文件中
理论上看起来这个过程是没问题的,但是这里埋了一个坑(由于自己的知识面不够广,没有认识到
InputStream.available()
的局限性
关于InputStream类的available()方法
要一次读取多个字节时,经常用到InputStream.available()方法,这个方法可以在读写操作前先得知数据流里有多少个字节可以读取。需要注意的是,如果这个方法用在从本
地文件读取数据时,一般不会遇到问题。
但如果是用于网络操作,就经常会遇到一些麻烦。比如,Socket通讯时,对方明明发来了1000个字节,但是自己的程序调用available()方法却只得到900,或者100,甚至是0,感觉有点莫名其妙,怎么也找不到原因。其实,这是因为网络通讯往往是间断性的,一串字节往往分几批进行发送。本地程序调用available()方法有时得到0,这可能是对方还没有响应,也可能是对方已经响应了,但是数据还没有送达本地。对方发送了1000个字节给你,也许分成3批到达,这你就要调用3次available()方法才能将数据总数全部得到。
所以我们应该采用别的方式去将Inputstream转换成file
1、使用Inputstream.read()方法,
private void ossObjectToFile(OSSObject ossObject, File file) throws IOException {
FileOutputStream out = null;
InputStream inputStream = ossObject.getObjectContent();
try {
out = new FileOutputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
int data;
try {
while((data = inputStream.read()) != -1) {
out.write(data);
}
inputStream.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
二、换一种读取inputstream所含字节数大小的方法
private void ossObjectToFile(OSSObject ossObject, File file) throws IOException {
InputStream inputStream = ossObject.getObjectContent();
//读取inputstream所含字节数,InputStream.available()方法需另外处理
byte[] bytes = Utils.readInputStream(inputStream);
//从InputStream中读出内存到byte[]中
inputStream.read(bytes);
//FileOutputStream写入文件
OutputStream outStream = new FileOutputStream(file);
outStream.write(bytes);
//关闭流
inputStream.close();
outStream.close();
}
public static byte[] readInputStream(InputStream inputStream) throws IOException {
byte[] buffer = new byte[1024];
int len = 0;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
while ((len = inputStream.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
bos.close();
return bos.toByteArray();
}
这样,不同类型的文件作为附件也能正常打开啦!!!
总结: