zoukankan      html  css  js  c++  java
  • 【小坑】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), "");
    }

    另一种方法是正则替换

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

    6、ajax下载

    由于ajax函数的返回类型只有xml、text、json、html等类型,没有“流”类型,所以通过ajax去请求该接口是无法下载。查看XHR,可以看到返回的报文体。

    • window.open("下载文件的后端接口")
    • 构建一个表单实现下载

    (参考:JS实现点击按钮,下载文件

  • 相关阅读:
    [Python] Unofficial Windows Binaries for Python Extension Packages
    [SublimeText] 之 Packages
    [Windows] Windows 8.x 取消触摸板切换界面
    [Shell] Backtick vs $() 两种方式内嵌值
    [OSX] 在 OS X 中安装 MacPorts 指南
    [OSX] 使用 MacPorts 安装 Python 和 pip 指南
    关于 g++ 编译器
    梦想成真,喜获微软MVP奖项,微软MVP FAQ?
    拥抱.NET Core,如何开发一个跨平台类库 (1)
    拥抱.NET Core,学习.NET Core的基础知识补遗
  • 原文地址:https://www.cnblogs.com/mr-yang-localhost/p/9702577.html
Copyright © 2011-2022 走看看