SpringBoot讀寫xml上傳到AWS存儲服務S3的示例
最近的工作涉及到了生成xml文件并上傳到AWS存儲服務S3這樣的處理。期間遇到了兩個問題,簡單記錄下:
springboot讀取xml模板異常 將生成的xml上傳到S3的問題springboot的版本是0,讀寫xml文件使用的是Dom4J,版本是1。逐個說明下遇到的這幾個問題。
1.springboot讀取xml模板異常
現階段是將xml模板文件存儲在springboot項目的resource目錄下的。具體路徑為
template/xxx.xml
最初是通過類加載器獲取文件路徑后再嘗試讀取模板文件的:
String fullPath = TemplateParser.class.getClassLoader().getResource(pathXml).getFile();File file = new File(fullPath);SAXReader reader = new SAXReader();Document document = reader.read(file);
通過類加器獲取到的文件路徑是:
file:/path/of/jar/springboot-xml.jar!/BOOT-INF/classes!/template/xxx.xml
不過我們都知道,springboot是將整個工程包括配置文件打成一個jar包后再直接運行。這樣想在linux的服務器上通過文件路徑找文件是注定找不到的。
后來改成直接通過SpringBoot提供的 ClassResource類來獲取resource路徑下的配置文件:
ClassPathResource resource = new ClassPathResource(pathXml);Document doc = reader.read(resource.getInputStream());
這里直接使用 InputStream讀取的模板文件。注意不要再嘗試通過調用 ClassResource實例的 getFile()方法來獲取文件,不然會遇到和之前同樣的問題。
額,期間還發生了無法將模板文件打進springboot項目運行時的jar文件這樣的問題。因為是將模板文件存儲在了resources的子目錄下,需要調整下maven打包的配置:
<resources> <resource><directory>src/main/resources</directory><filtering>true</filtering><includes> <include>**/*</include></includes> </resource></resources>
下面這幾行如果沒有的話需要加上,不然會讀取不到子目錄中的配置文件:
<includes><include>**/*</include> </includes>
2.將生成的xml上傳到S3
AWS提供的最便捷的上傳文件接口是這個:
public PutObjectResult putObject(String bucketName, String key, File file) throws SdkClientException, AmazonServiceException;
這個接口通過 File實例來執行上傳。所以我一開始的想法是先生成一個臨時文件保存在服務器本地,讀取本地臨時文件為 File執行上傳,最后再刪掉本地的臨時文件。這個思路是沒問題的,在本地執行也OK。但是在生產環境,由于權限相關的問題,生成臨時文件失敗了。
不想再去折騰權限相關的事情,所以將出路寄托在了AWS提供的另一個接口上:
public PutObjectResult putObject( String bucketName, String key, InputStream input, ObjectMetadata metadata) throws SdkClientException, AmazonServiceException;
也就是說考慮將xml文件內容輸出到 InputStream,然后再將InputStream上傳到S3。一切都在內存里執行,不依賴外部文件系統也就不會有文件權限的問題。
這個方案的問題在于 ObjectMetaData這個類有點兒黑箱的意思。該怎么設置需要進行一些摸索。看了一遍這個類的接口文檔,需要調用的也就這兩個set方法:
/** * Set the date when the object is no longer cacheable. */ public void setHttpExpiresDate(Date httpExpiresDate) {this.httpExpiresDate = httpExpiresDate; }/** * <p> * Sets the Content-Length HTTP header indicating the size of the * associated object in bytes. * </p> * <p> * This field is required when uploading objects to S3, but the AWS S3 Java * client will automatically set it when working directly with files. When * uploading directly from a stream, set this field if * possible. Otherwise the client must buffer the entire stream in * order to calculate the content length before sending the data to * Amazon S3. * </p> */ public void setContentLength(long contentLength) {metadata.put(Headers.CONTENT_LENGTH, contentLength); }
其中后者(文件長度)是AWS建議設置的,不設置會在處理的時候給出WARN。根據方法文檔也可以看到,如果不設置,在上傳的時候就會在內存中緩存整個信息流來計算文件長度。
至于前者是上傳到S3文件的緩存過期時間,酌情設置即可。
另一個需要解決的問題就是怎么將Dom4j生成的 Document輸出再讀取到 InputStream中。這里用到了 XmlWritter類,具體實現如下:
XMLWriter xmlWriter = new XMLWriter(outputStream, OutputFormat.createCompactFormat());xmlWriter.write(doc);xmlWriter.close();return new ByteArrayInputStream(outputStream.toByteArray());
驗證了一下,這個方法是可行的。修改后生產環境沒有再報錯。
向AWS S3存儲服務上傳文件的實現代碼在這篇文章里:Java實現上傳文件到AWS S3
End!
以上就是SpringBoot讀寫xml上傳到S3的示例的詳細內容,更多關于SpringBoot讀寫xml的資料請關注好吧啦網其它相關文章!
相關文章:
