导出问题处理

问题描述

测试出来一个问题,使用地市的角色,导出数据然后超过了20w的数据,提示报错,我还以为是偶然的问题,然后是发现是普遍的问题,本地环境复现了,然后是,这个功能是三套角色,分别是集团,省份,地市。我用集团,省份角色查了这个地市,导出数据没有问题,然后我就好奇了。

报错问题

java 复制代码
2024-10-22 15:17:05.612 ERROR 38604 --- [ XNIO-1 task-38] c.a.a.c.AssetDetailsQueryLocalController : exception's message:68
2024-10-22 15:18:59.375  INFO 38604 --- [ XNIO-1 task-38] cn.chinaunicom.ams.utils.EasyExcelUtils  : 压缩完成,耗时:5877 ms
2024-10-22 15:18:59.504 ERROR 38604 --- [ XNIO-1 task-38] cn.chinaunicom.core.util.CephUtil        : exception's message:java.io.FileInputStream.open0(Native Method)
2024-10-22 15:18:59.511 ERROR 38604 --- [ XNIO-1 task-38] cn.chinaunicom.core.util.CephUtil        : exception's message:上传文件:对象名export\2024\10\22\资产明细报表_20241022_151557260.xlsx,全路径file/ams/export\2024\10\22\资产明细报表_20241022_151557260.xlsx
2024-10-22 15:18:59.512 ERROR 38604 --- [ XNIO-1 task-38] c.a.a.c.AssetDetailsQueryLocalController : exception's message:cn.chinaunicom.core.util.CephUtil.uploadExportFile(CephUtil.java:191)

代码描述

java 复制代码
 /**
     * 资产全量报表查询-导出资产全量报表信息 期间查询
     * @param response
     * @param request
     * @param requestBody
     */
    @ResponseBody
    @PostMapping("/exportDetailViewListPeriodName")
    @ApiOperation(value = "资产全量报表查询-导出资产全量报表信息", notes = "资产全量报表查询-导出资产全量报表信息")
    @OperateLog("资产全量报表查询-导出资产全量报表信息")
    @RsaDecrypt(msg = "查询失败", isModuleSign = true, moduleName = "AssetDetailsQueryAllRequestBody")
    public void exportDetailViewListPeriodName(AssetDetailsQueryLocalRequestBody requestBody,HttpServletResponse response, HttpServletRequest request) {
        try {
            //j后台取值 账簿信息
            List<String> bookTypeCodeList = constantAbtOracleService.getBookTypeCodes("1");

            /**
             * 账簿后台获取
             */

            if(bookTypeCodeList.size() == 1){
                requestBody.setBookTypeCode(bookTypeCodeList.get(0));
            }
            String condition = assetDetailsQueryLocalService.queryViewListForExportcondition(requestBody);
            if(StringUtils.isNotBlank(requestBody.getManufacturerName())){
                requestBody.setManufacturerName(URLDecoder.decode(requestBody.getManufacturerName()));
            }
            long start = System.currentTimeMillis();
            int count = 0;
            //批量资产编号
            String[] assetNumberStr = null;
            if (requestBody.getAssetNumbers() != null && !("").equals(requestBody.getAssetNumbers())) {
                assetNumberStr = requestBody.getAssetNumbers().split(",");
            }
            requestBody.setAssetNumberStr(assetNumberStr);

            //批量资产标签号
            String[] tagNumberStr = null;
            if (requestBody.getTagNumbers() != null && !("").equals(requestBody.getTagNumbers())) {
                tagNumberStr = requestBody.getTagNumbers().split(",");
            }
            requestBody.setTagNumberStr(tagNumberStr);


            Date nowTime = new Date();
            // 往数据库存储的路径(不含配置的前缀路径)
            String dbSavePath = "export" + File.separator + new SimpleDateFormat("yyyy").format(nowTime)
                    + File.separator + new SimpleDateFormat("MM").format(nowTime)
                    + File.separator + new SimpleDateFormat("dd").format(nowTime)
                    + File.separator;
            // 临时文件实际保存路径
            String fileSavePath = ExportExcelUtils.getImplementTemplate(request) + dbSavePath;
            // 获取保存路径,没有对应目录的话自行创建
            String savePath = FileUtil.createDir(fileSavePath);
            Date d = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmssSSS");
            String dateNowStr = sdf.format(d);

            AssetExportFile exportFile = new AssetExportFile();
            String fileName="";
            String fileType="";

            String fileNameInfo="";
            fileNameInfo = "资产明细报表_";

            fileName=fileNameInfo+dateNowStr;
            exportFile.setFileName(fileName);

            //导出临时文件的命名
            String filePathFront= savePath + "资产明细报表_" + dateNowStr;
            // 数据库里存的文件路径即上传到云平台的文件命名
            exportFile.setFilePath(filePathFront);
            NowUser nowUser = WebUtil.getNowUser();
            exportFile.setCreatedBy(nowUser.getStaffId());
            Date date = new Date();
            SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            //导出文件记录中新增一条记录
            exportFile.setCreatedDate(sdf1.format(date));
            exportFile.setExportStatus(FlowUtils.EXPORT_START);
            exportFile.setCreateName(nowUser.getStaffName());
            exportFile.setFileCondition(condition);

            final int file1 = exportFileService.insertExportFile(exportFile);
            String exportFileId = exportFile.getId();


//            String endChar = requestBody.getBookTypeCode().substring(3,5);
            String endChar = assetDetailsQueryAllService.getTableNameByBookTypeCode(requestBody.getBookTypeCode());
            String periodName = requestBody.getPeriodName().replace("-","");

            requestBody.setTableName("CAMS_ASSET_DETAIL_" + endChar+"_"+periodName);
            //1、根据查询条件获取集合-erp
            List<AssetDetailsExcel> result=new ArrayList<>();//返回结果
            //开始查询的行数
            long startTime = System.currentTimeMillis();
            try{
                //1、根据查询条件获取集合-erp
                result = assetDetailsQueryLocalService.queryViewListForExportPeriodName(requestBody);
            }
            catch(Exception exception){
                log.error("导出数据异常:" + exception);
            }
            long endTime = System.currentTimeMillis();

            count=result.size();

            if(count>FlowUtils.COUNT_FOR_TYPE){//生成zip格式
                fileName=fileNameInfo+dateNowStr+".zip";
                fileType=FlowUtils.ZIP_TYPE;
                exportFile.setFileType(fileType);
            }else{// 生成xlsx格式
                fileName= fileNameInfo+dateNowStr+".xlsx";
                fileType=FlowUtils.XLSX_TYPE;
                exportFile.setFileType(fileType);
            }
            exportFile.setFileName(fileName);

            // 导出临时文件最终命名和路径
            String finalFilePath = filePathFront + "." + fileType;
            //上传到服务器的实际文件的命名
            String finalFileName = dbSavePath + "资产明细报表_" + dateNowStr + "." + fileType;
            // 数据库里存的文件路径即上传到云平台的文件命名
            exportFile.setFilePath(finalFileName);

            log.error("exception's message:{}", String.valueOf((endTime - startTime) / 1000));
            //一个excel的总数据量
            int oneExcelSize = FlowUtils.ONE_EXCEL_SIZE;
            //需导出的总数据量
            int resultCount = result.size();
            //计算需要导出的excel的个数
            int excelCount = resultCount%oneExcelSize==0?resultCount/oneExcelSize:(resultCount/oneExcelSize +1);
            //声明fileList,大小为excelCount
            final List<File> resultFileList = new ArrayList<>(excelCount);


            EasyExcelUtils easyExcelUtils = new EasyExcelUtils();
            if (excelCount>1){
                // 多个文件,多线程并发写入
                for(int i=0;i<excelCount;i++){
                    resultFileList.add(null);
                }

                for(int i=0;i<excelCount;i++){
                    final int index =i;
                    // 按每个excel的数据量大小来切分查询结果list
                    final List<AssetDetailsExcel> res = resultCount<(index+1)*oneExcelSize?result.subList(index*oneExcelSize,resultCount):result.subList(index*oneExcelSize,(index+1)*oneExcelSize);
                    //文件命名
                    String excelFileName = savePath+"资产明细报表_"+dateNowStr+"-"+String.valueOf(i+1)+".xlsx";
                    File file = new File(excelFileName);
                    resultFileList.set(index,file);
                    EasyExcel.write(excelFileName,AssetDetailsExcel.class).sheet("sheet").doWrite(res);

                }
                // 压缩文件
                final File file = easyExcelUtils.compressFile(resultFileList, true, exportFileId, filePathFront);
            } else {
                EasyExcel.write(finalFilePath,AssetDetailsExcel.class).sheet("sheet").doWrite(result);
            }
            //文件上传到慧企平台 --todo
            CephUtil.uploadExportFile(finalFileName, finalFilePath);
            //文件上传到慧企平台后删除临时文件 todo
            boolean resultTemp = valueSetController.executeFile(finalFilePath);
            // 更新导出文件记录
            exportFile.setId(exportFileId);
            exportFile.setExportStatus(FlowUtils.EXPORT_DONE);
            exportFileService.updateStatusFileNameById(exportFile);

            long end = System.currentTimeMillis();

        } catch (Exception e) {
            log.error("exception's message:{}",e.getStackTrace());
        }
    }


	/**
	 * 本地文件上传到ceph
	 *
	 * @param objName 上传上去的对象名(经测试长度不能超1024)
	 * @param fileAllPath 将要上传的本地文件全路径
	 * @return
	 */
	public static boolean uploadExportFile(String objName, String fileAllPath) throws IOException {
		FileInputStream fis = null;
		try {
			AmazonS3 conn = connCeph();
			File file = new File(fileAllPath);
			int imageSize = 0;
			try {
				fis = new FileInputStream(file);
				imageSize = fis.available();
			} catch (Exception e) {
				log.error("exception's message:{}",e.getStackTrace());
			}
			ObjectMetadata om = new ObjectMetadata();
			om.setContentLength(imageSize);
			conn.putObject(DEFAULT_BUCKET_NAME, objName, fis, om);
			if (ONLINE.equals("true")) {
				fis = new FileInputStream(file);
				AmazonS3 conn2 = connCeph2();
				conn2.putObject(DEFAULT_BUCKET_NAME2, objName, fis, om);
				log.error("exception's message:{}", "上传文件:对象名" + objName + ",全路径" + fileAllPath);
				return true;
			}
		} catch (Exception e) {
			log.error("exception's message:{}", "上传文件:对象名" + objName + ",全路径" + fileAllPath);
		} finally {
			fis.close();
		}
		return false;
	}

问题处理

真的找了好久,想到了一个思路才发现了问题处理,首先,这个报错提示是找不到文件,然后开始倒查。首先,这个功能是,有三套前端,两套后端,然后这也是我后面反应过来的问题,问题是出现在地市的角色上,地市角色使用本功能因为数据量在20w,增加一个条件之后导出了300条数据,直到我一条一条debug,发现提示找不到文件,然后在删除文件之前我去debug,找了具体的问题。

直到发现了这个问题,我才想起来,之前我改了一版,修改的是最大的文件数是从100000变成了300000,然后发现我只改了一个静态变量,只改了一个文件的判断是不是最多条的数量,但是一个excel中的最大条数还是100000,然后就提示报错了,该说不说这个问题我真的找了好久,因为确实是文件找不到报错的地方。

相关推荐
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭8 分钟前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
暮湫24 分钟前
泛型(2)
java
南宫生33 分钟前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
转码的小石41 分钟前
12/21java基础
java
李小白661 小时前
Spring MVC(上)
java·spring·mvc
GoodStudyAndDayDayUp1 小时前
IDEA能够从mapper跳转到xml的插件
xml·java·intellij-idea
装不满的克莱因瓶2 小时前
【Redis经典面试题六】Redis的持久化机制是怎样的?
java·数据库·redis·持久化·aof·rdb
n北斗2 小时前
常用类晨考day15
java
骇客野人2 小时前
【JAVA】JAVA接口公共返回体ResponseData封装
java·开发语言
yuanbenshidiaos3 小时前
c++---------数据类型
java·jvm·c++