java异步导出表格,记录导出进度,导出完成才能下载业务

贴一下

import com.alibaba.fastjson.JSON;
import com.paratera.lpbs.consts.Consts;
import com.paratera.lpbs.controller.BaseController;
import com.paratera.lpbs.entity.AsyncJobStatusEnum;
import com.paratera.lpbs.entity.vo.VoAsyncTask;
import com.paratera.lpbs.monitor.AsyncTaskManager;
import com.paratera.lpbs.service.ExportService;
import com.paratera.lpcomm.annotation.AuditLogRecord;
import com.paratera.lpcomm.annotation.LoginPass;
import com.paratera.lpcomm.consts.AuditModel;
import com.paratera.lpcomm.consts.AuditType;
import com.paratera.lpcomm.entity.BillingTypeEnum;
import com.paratera.lpcomm.entity.Error;
import com.paratera.lpcomm.entity.QueueType;
import com.paratera.lpcomm.utils.DateFomatUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Sort;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.*;
import java.net.URLEncoder;
import java.text.ParseException;
import java.util.List;
import java.util.UUID;

import static com.paratera.lpbs.consts.Consts.JOB_LIST;


@RestController
@RequestMapping("/api/admin")
@Api(tags = "导出控制层(admin)", produces = "application/json", value = "导出接口", consumes = "application/json")
@ApiResponses(value = { @ApiResponse(code = 200, message = "successfully"),
        @ApiResponse(code = 401, message = "You are not authorized to view the resource", response = Error.class),
        @ApiResponse(code = 403, message = "Accessing the resource you were trying to reach is forbidden", response = Error.class),
        @ApiResponse(code = 404, message = "The resource you were trying to reach is not found", response = Error.class),
        @ApiResponse(code = 500, message = "error", response = Error.class) })
public class ExportAdminController extends BaseController {

    @Autowired
    private ExportService exportService;

    @Autowired
    private AsyncTaskManager asyncTaskManager;

    @Autowired
    public RedisTemplate<String, Object> redisTemplate;

    @Value("${spring.config.billing.file-path-profile:disk/}")
    private String filePathProfile;


    @GetMapping("/billing/job/list/export")
    @AuditLogRecord(content = "导出作业清单", type = AuditType.SCC_JOB_LIST_EXPORT, model = AuditModel.BILLING)
    @ApiOperation(nickname = "jobListExport", value = "作业清单导出接口", httpMethod = "GET", produces = "application/json")
    public VoAsyncTask export(@RequestParam(name = "searchUid", required = false) String searchUid,
                              @RequestParam(name = "searchRawJobId", required = false) String searchRawJobId,
                              @RequestParam(name = "billingType", required = false) BillingTypeEnum billingType,
                              @RequestParam(name = "queueType", required = false) QueueType queueType,
                              @RequestParam(name = "zoneClusterQueues", required = false) List<String> zoneClusterQueues,
                              @RequestParam(name = "softwares", required = false) List<String> softwares,
                              @RequestParam(name = "clusters", required = false) List<String> clusters,
                              @RequestParam(name = "intervalStartTimeStart") String intervalStartTimeStart,
                              @RequestParam(name = "intervalStartTimeEnd") String intervalStartTimeEnd,
                              @RequestParam(name = "page", required = false, defaultValue = "1") int page,
                              @RequestParam(name = "size", required = false, defaultValue = "100") int size,
                              @RequestParam(name = "order", required = false, defaultValue = "DESC") Sort.Direction order,
                              @RequestParam(name = "orderBy", required = false, defaultValue = "createdDate") String orderBy)
            throws IOException {

        initFilePathDisk(filePathProfile);
        String filePath = filePathProfile + UUID.randomUUID() + ".csv";
        String[] header = { "分区", "作业ID", "应用软件", "队列别名", "提交时间", "计费开始时间", "计费截止时间", "开始时间", "结束时间", "进程数量", "计费时长",
                "作业时长", "作业空闲时长", "作业空闲时长占比", "核时/卡时", "计费模式", "排队时长", "排队原因", "超算账号", "用户账号" };

        VoAsyncTask voAsyncTask = asyncTaskManager.initTask(filePath, intervalStartTimeStart, intervalStartTimeEnd);
        exportService.asyncExport(voAsyncTask, filePath, header, searchUid, searchRawJobId, billingType, queueType,
                zoneClusterQueues, softwares, clusters, intervalStartTimeStart, intervalStartTimeEnd, page, Consts.SIZE,
                order, orderBy);
        return voAsyncTask;
    }

    @GetMapping("/billing/job/list/export/progress")
    @AuditLogRecord(content = "查询作业清单导出进度", type = AuditType.SCC_JOB_LIST_EXPORT, model = AuditModel.BILLING)
    @ApiOperation(nickname = "jobListExport", value = "作业清单导出进度查询接口", httpMethod = "GET", produces = "application/json")
    public VoAsyncTask getProgress(@RequestParam(name = "taskId") String taskId) {
        String jsonString = (String) redisTemplate.opsForHash().get(JOB_LIST, taskId);
        return JSON.parseObject(jsonString, VoAsyncTask.class);
    }


    @GetMapping("/billing/job/list/export/download")
    @AuditLogRecord(content = "下载作业清单", type = AuditType.SCC_JOB_LIST_EXPORT, model = AuditModel.BILLING)
    @ApiOperation(nickname = "jobListExport", value = "作业清单文件下载接口", httpMethod = "GET", produces = "text/comma-separated-values")
    public void exportDownload(@RequestParam(name = "taskId") String taskId) throws IOException, ParseException {
        String jsonString = (String) redisTemplate.opsForHash().get(JOB_LIST, taskId);
        VoAsyncTask voAsyncTask = JSON.parseObject(jsonString, VoAsyncTask.class);
        if(voAsyncTask.getStatus() == AsyncJobStatusEnum.ACTIVE && voAsyncTask.getProgress() == 100.00) {
            String filePath = voAsyncTask.getFilePath();
            File f = new File(filePath);
            if (!f.exists()) {
                return;
            }
            BufferedInputStream br = new BufferedInputStream(new FileInputStream(f));
            byte[] buf = new byte[1024];
            int len = 0;

            String csvName = DateFomatUtils.getCsvName(voAsyncTask.getIntervalStartTimeStart(), voAsyncTask.getIntervalStartTimeEnd(), JOB_LIST);
            String fileNameURL = URLEncoder.encode(csvName, "UTF-8");

            resp.reset();
            resp.setContentType("application/x-msdownload");
            resp.setHeader("Content-Disposition", "attachment; filename=" + fileNameURL);

            OutputStream out = resp.getOutputStream();
            while ((len = br.read(buf)) > 0){
                out.write(buf, 0, len);
            }
            br.close();
            out.close();
        }
    }

    private void initFilePathDisk(String path) {
        File file = new File(path);
        if (!file.exists()) {
            file.mkdirs();
        }
    }
}
import com.alibaba.fastjson.JSON;
import com.paratera.lpbs.consts.Consts;
import com.paratera.lpbs.controller.admin.SccJobAdminController;
import com.paratera.lpbs.entity.AsyncJobStatusEnum;
import com.paratera.lpbs.entity.vo.VoAsyncTask;
import com.paratera.lpbs.entity.vo.VoBillSccJob;
import com.paratera.lpbs.utils.CsvWriterUtils;
import com.paratera.lpcomm.entity.BillingTypeEnum;
import com.paratera.lpcomm.entity.QueueType;
import com.paratera.lpcomm.vo.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Arrays;
import java.util.List;

import static com.paratera.lpbs.consts.Consts.JOB_LIST;

@Service
public class ExportService {

    @Autowired
    private SccJobAdminController sccJobAdminControlle;

    @Autowired
    public RedisTemplate<String, Object> redisTemplate;


    @Async
    public void asyncExport(VoAsyncTask voAsyncTask, String filePath, String[] header,
                            String searchUid, String searchRawJobId, BillingTypeEnum billingType, QueueType queueType,
                            List<String> zoneClusterQueues, List<String> softwares, List<String> clusters, String intervalStartTimeStart,
                            String intervalStartTimeEnd, int page, int size, Sort.Direction order, String orderBy) throws IOException {

        File file = new File(filePath);
        OutputStreamWriter ow = new OutputStreamWriter(new FileOutputStream(file), "gbk");
        // 写header
        Arrays.stream(header).forEach(it -> {
            try {
                ow.write(it);
                ow.write(",");
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
        ow.write("\r\n");

        Page<VoBillSccJob> voBillSccJobPage = sccJobAdminControlle.billList(searchUid, searchRawJobId, billingType, queueType,
                zoneClusterQueues, softwares, clusters, intervalStartTimeStart, intervalStartTimeEnd, page, Consts.SIZE,
                order, orderBy);

        for (int i = 1; i <= voBillSccJobPage.getTotalPage(); i++) {
            Page<VoBillSccJob> billSccJobPage = sccJobAdminControlle.billList(searchUid, searchRawJobId, billingType, queueType,
                    zoneClusterQueues, softwares, clusters, intervalStartTimeStart, intervalStartTimeEnd, i,
                    Consts.SIZE, order, orderBy);
            // 写入本地磁盘
            for (VoBillSccJob voBillSccJob : billSccJobPage.getData()) {
                List<String> curRowList = CsvWriterUtils.jobListContent(voBillSccJob);
                curRowList.forEach(it -> {
                    try {
                        ow.write(it);
                        ow.write(",");
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                });
                ow.write("\r\n");
            }

            // 记录导出进度
            voAsyncTask.setProgress(((double) i)/voBillSccJobPage.getTotalPage()*100);
            redisTemplate.opsForHash().put(JOB_LIST, voAsyncTask.getTaskId(), JSON.toJSONString(voAsyncTask));
        }
        voAsyncTask.setStatus(AsyncJobStatusEnum.ACTIVE);
        redisTemplate.opsForHash().put(JOB_LIST, voAsyncTask.getTaskId(), JSON.toJSONString(voAsyncTask));
        ow.flush();
        ow.close();
    }

}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Java异步导出Excel可以通过使用多线程或异步任务来实现。以下是使用异步任务的示例代码: 1. 首先,你需要定义一个实现了Callable接口的任务类,用来执行Excel导出操作。例如: ``` public class ExcelExportTask implements Callable<File> { private List<Data> dataList; public ExcelExportTask(List<Data> dataList) { this.dataList = dataList; } @Override public File call() throws Exception { // 执行Excel导出操作,返回导出文件 return ExcelUtils.export(dataList); } } ``` 2. 在Controller中,定义一个异步导出Excel的方法。例如: ``` @GetMapping("/export") public Callable<ResponseEntity<byte[]>> exportExcel() { List<Data> dataList = dataService.getDataList(); ExcelExportTask task = new ExcelExportTask(dataList); return () -> { try { File file = task.call(); byte[] bytes = FileUtils.readFileToByteArray(file); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); headers.setContentDispositionFormData("attachment", file.getName()); return new ResponseEntity<>(bytes, headers, HttpStatus.OK); } catch (Exception e) { e.printStackTrace(); return null; } }; } ``` 3. 在异步导出Excel的方法中,我们首先获取需要导出的数据,然后创建一个ExcelExportTask对象,并返回一个Callable对象。在Callable的call()方法中,执行Excel导出操作,并返回导出的文件。最后,将导出的文件转换成byte数组,并返回一个ResponseEntity对象,以供前端下载。 这样,当用户请求异步导出Excel时,不会阻塞主线程,而是异步执行Excel导出操作。用户可以继续浏览页面或进行其他操作,直到下载Excel文件。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值