【小坑】java下載excel文件


excel文件的導入導出是很常見的功能,這次做了個下載的功能,踩了一些坑,記下來避免以后重復踩……

1、inputstream序列化問題

Could not write JSON document: No serializer found for class java.io.FileDescriptor and no properties discovered to create BeanSerializer

客戶端調取服務端上傳,從前台獲取的file文件中拿到inputstream,做一些判斷后(格式校驗、大小校驗等)將inputstream作為參數傳給服務端報如下錯誤:

Failed to write HTTP message: org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON document: No serializer found for class java.io.FileDescriptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)  

因為輸入流InputStream序列化錯誤。計算機傳輸數據實際上是二進制的傳輸,將inputstream轉化為字節數組就可以通過網絡流進行傳輸了,使用byte[] 來替代InputStream。

2、讀取resources下的xlsx文件

將xlsx文件放項目resources目錄下,通過以下代碼本地調試通過: 

InputStream templateStream = ClassUtils.getDefaultClassLoader().getResourceAsStream(TEMPTALTE);
int len = templateStream.available();
byte[] readBuf = new byte[len];
templateStream.read(readBuf, 0, len);

將inputstream讀入到readBuf里,再將readBuf傳給服務端。本地測試通過,放到測試環境,於是開始了填坑……

3、java.util.zip.ZipException: invalid stored block lengths

(參考:Poi讀取Excle報錯 java.util.zip.ZipException: invalid stored block lengths)

是因為打為jar包時對resources資源文件進行了轉碼壓縮,直接讀取inputstream使用無法識別。將jar包解壓縮,打開里面的xlsx文件,報錯提示:

  

按文中辦法添加maven插件,打包時對xls和xlsx文件不進行轉碼壓縮。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <version>2.6</version>
    <artifactId>maven-resources-plugin</artifactId>
    <configuration>
         <encoding>UTF-8</encoding>
         <nonFilteredFileExtensions>
             <nonFilteredFileExtension>xlsx</nonFilteredFileExtension><!--xlsx結尾的文件不壓縮-->
         </nonFilteredFileExtensions>
    </configuration>
</plugin>

添加排除xlsx打包壓縮之后,從打完的jar包解壓縮出的xlsx可以正常打開。

4、read讀取的問題

由提示信息得知:這個問題報的是格式或擴展名的問題。而擴展名是沒有問題了,經檢查發現是格式的問題,本地調試的時候讀取的是正確完整的byte[]數據,測試環境讀取的不全或沒有讀取數據。

查看inputstream的 read(byte b[], int off, int len) 方法

 

* Reads up to <code>len</code> bytes of data from the input stream into
* an array of bytes. An attempt is made to read as many as
* <code>len</code> bytes, but a smaller number may be read.
* The number of bytes actually read is returned as an integer.

修改如下:

InputStream templateStream = ClassUtils.getDefaultClassLoader().getResourceAsStream(TEMPLATE);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[2048];
int num = -1;
while((num = templateStream.read(buffer)) != -1){
  baos.write(buffer, 0, num);
}
baos.flush();
baos.toByteArray();
baos.close();

5、excel單元格包含換行

讀取excel到json,然后通過fastjson反序列化為list對象。當excel單元格包含換行符時報錯:(參考:用java導入導出excel如何去掉軟回車和硬回車

Illegal unquoted character ((CTRL-CHAR, code 10)): has to be escaped using backslash to be included in string value excel

一種方法是替換掉excel的特殊字符

for(int i=10;i<14;i++)
{
   str = str.replaceAll(String.valueOf((char)i), "");
}

另一種方法是正則替換

//空格\t、回車\n、換行符\r、制表符\t
Pattern p = Pattern.compile("\\s*|\t|\r|\n");
Matcher m = p.matcher(str);
dest = m.replaceAll("");

6、ajax下載

由於ajax函數的返回類型只有xml、text、json、html等類型,沒有“流”類型,所以通過ajax去請求該接口是無法下載。查看XHR,可以看到返回的報文體。

  • window.open("下載文件的后端接口")
  • 構建一個表單實現下載

(參考:JS實現點擊按鈕,下載文件


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM