SpringBoot读写xml上传到S3

最近的工作涉及到了生成xml文件并上传到AWS存储服务S3这样的处理。期间遇到了两个问题,简单记录下:

  1. springboot读取xml模板异常
  2. 将生成的xml上传到S3的问题

springboot的版本是2.1.9.RELEASE,读写xml文件使用的是Dom4J,版本是2.1.3。逐个说明下遇到的这几个问题。

1.springboot读取xml模板异常

现阶段是将xml模板文件存储在springboot项目的resource目录下的。具体路径为

最初是通过类加载器获取文件路径后再尝试读取模板文件的:

通过类加器获取到的文件路径是:

不过我们都知道,springboot是将整个工程包括配置文件打成一个jar包后再直接运行。这样想在linux的服务器上通过文件路径找文件是注定找不到的。

后来改成直接通过SpringBoot提供的ClassResource类来获取resource路径下的配置文件:

这里直接使用InputStream读取的模板文件。注意不要再尝试通过调用ClassResource实例的getFile()方法来获取文件,不然会遇到和之前同样的问题。

额,期间还发生了无法将模板文件打进springboot项目运行时的jar文件这样的问题。因为是将模板文件存储在了resources的子目录下,需要调整下maven打包的配置:

下面这几行如果没有的话需要加上,不然会读取不到子目录中的配置文件:

2.将生成的xml上传到S3

AWS提供的最便捷的上传文件接口是这个:

这个接口通过File实例来执行上传。所以我一开始的想法是先生成一个临时文件保存在服务器本地,读取本地临时文件为File执行上传,最后再删掉本地的临时文件。这个思路是没问题的,在本地执行也OK。但是在生产环境,由于权限相关的问题,生成临时文件失败了。

不想再去折腾权限相关的事情,所以将出路寄托在了AWS提供的另一个接口上:

也就是说考虑将xml文件内容输出到InputStream,然后再将InputStream上传到S3。一切都在内存里执行,不依赖外部文件系统也就不会有文件权限的问题。

这个方案的问题在于ObjectMetaData这个类有点儿黑箱的意思。该怎么设置需要进行一些摸索。看了一遍这个类的接口文档,需要调用的也就这两个set方法:

其中后者(文件长度)是AWS建议设置的,不设置会在处理的时候给出WARN。根据方法文档也可以看到,如果不设置,在上传的时候就会在内存中缓存整个信息流来计算文件长度。

至于前者是上传到S3文件的缓存过期时间,酌情设置即可。

另一个需要解决的问题就是怎么将Dom4j生成的Document输出再读取到InputStream中。这里用到了XmlWritter类,具体实现如下:

验证了一下,这个方法是可行的。修改后生产环境没有再报错。

向AWS S3存储服务上传文件的实现代码在这篇文章里:Java实现上传文件到AWS S3

End!

发表评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据