解决java web开发中常见的大量数据导出Excel超时(504)问题

3 篇文章 0 订阅
1 篇文章 0 订阅
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;

import com.travelzen.framework.net.http.TZHttpClient;
import com.travelzen.tops.front.ota.member.item.CustomerItem;

public class CSV {

    /**
     * 目标输出流
     */
    private OutputStream stream;
    /**
     * 表头
     */
    private Map<String,String> fields;

    /**
     * 数据源model所有字段map
     */
    private static Map<String, Field> fieldMap = new HashMap<>();

    public CSV(HttpServletResponse response,Map<String,String> fields,String fileName,Class<?> clz) throws IOException{
        if(response == null || fields == null || fileName == null || clz == null)
            throw new IllegalArgumentException();
        getFieldMap(clz,fieldMap);
        this.stream = response.getOutputStream();
        this.fields = fields;
        response.setContentType("application/octet-stream;charset=GBK");
        response.setHeader("Content-Disposition", "attachment;fileName="+ fileName);
        //写表头,生成指定名字的文件,返回客户端
        StringBuilder hb = new StringBuilder();
        for(Entry<String, String> e : fields.entrySet())
            hb.append(e.getValue()+",");
        stream.write(hb.substring(0, hb.length() - 1).getBytes("GBK"));
        stream.flush();
    }
    /**
     * 往表格中插入记录
     */
    public void write(List<Object> data) throws IllegalArgumentException, IllegalAccessException, IOException{
        for(Object o : data){
            StringBuilder sb = new StringBuilder();
            sb.append("\n");
            for(String field : fields.keySet()){
                Field f = fieldMap.get(field);
                f.setAccessible(true);
                Object value = f.get(o);
                if(value == null || StringUtils.isBlank(value.toString())){
                    sb.append(" ,");
                } else if (f.getType() == Date.class) {
                    sb.append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(value) + ",");
                } else if (f.getType() == DateTime.class) {
                    sb.append(((DateTime)value).toString("yyyy-MM-dd HH:mm:ss") + ",");
                } else {
                    String tmp = value.toString();
                    if(tmp.contains(","))
                        tmp = tmp.replace(",", "\",\"");
                    sb.append(value.toString() + ",");
                }
            }
            stream.write(sb.substring(0, sb.length() - 1).getBytes("GBK"));
            stream.flush();
        }
    }

    public void close() throws IOException{
        stream.close();
    }

    private static <T extends Object> void getFieldMap(Class<T> clz, Map<String, Field> result) {
        for (Field field : clz.getDeclaredFields()) {
            result.put(field.getName(), field);
        }
        if (clz.getSuperclass() != null) {
            getFieldMap(clz.getSuperclass(), result);
        }
    }
}

web开发中常见的准备Excel数据需要从数据库查询数据,或者跨系统调用接口查询数据,耗费大量时间,因此未及时向浏览器返回数据,导致504超时。

本工具使用ServletOutputStream分段的往浏览器flush数据。调用方式:先new CSV(),传入指定参数,不断的调用wirte()方法往浏览器写入数据,最后调用close方法关闭流。

本工具导出的文件格式为.csv文件,windows office工具默认编码为ASCI,wps会匹配各种编码,libreOffice calc可以指定编码,故此设置编码为GBK,兼容三种Excel软件,也可根据自身需求设置编码。

本工具只处理了CSV中”,”的转码,对于双引号并未处理。

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Java导出大量数据Excel时,可能会因为数据量过大导致前端请求超时。这是由于以下几个原因引起的: 1. 数据量大:导出大量数据需要较长的处理时间和较高的系统资源消耗。如果数据量远远超过前端请求能承受的极限,前端请求时间可能超出设置的时间限制,从而导致超时。 2. 网络传输限制:在数据量较大的情况下,数据的传输时间也会相应增加。如果网络传输速度慢或网络连接不稳定,请求可能会在传输过程超时。 为了解决这个问题,可以考虑以下几个方案: 1. 分批导出:将大量数据分成小批次进行导出。可以在前端通过多次请求来获取分批次的数据,然后在后台进行数据导出。这样可以避免单次请求时间过长导致的超时问题。 2. 后台异步导出:当前端发起数据导出请求时,后台可以先返回一个任务标识,告知前端任务已经在后台进行处理。后台将数据导出的过程放在一个异步任务执行,不会阻塞前端请求。前端可以轮询任务状态,直到任务完成并提供下载链接。 3. 压缩文件导出:将导出数据以压缩文件的形式返回给前端,可以减小数据的传输量,加快数据传输速度。前端可以在接收到文件后再进行解压和处理。 4. 前端分页获取:前端可以通过分页的方式获取数据,每次请求只获取一页的数据。这样可以减少单次请求的数据量,降低请求超时的风险。 通过上述方案,可以有效地解决Java导出Excel数据量大导致前端请求超时问题,提高系统的可用性和用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值