一、背景 本地浏览器导出功能因数据量大,出现浏览器卡顿、崩溃的情况下,我们可以通过优化代码、sql来缓解,当出现非代码优化所能处理卡顿的情况时,就需要换种思路处理导出功能了,那就是 实现异步导出(浏览器点击导出时,执行异步方法,边写入处理任务、边执行导出功能,这时很慢的导出在后台运行,前台客户无感知,等异步下载完成后,更薪任务状态,通知客户下载完毕,可以下载了。这条任务需要存入数据表里)。实现思路就是:后端生成文件后上传至阿里云OSS空间,上传完成后,更新任务状态,通知客户去下载文件,此时下载的文件是从阿里云OSS上下载的。

Java处理文件上传OSS 可参考官方文档: 阿里云OSS官方手册 里面有示例工程,可下载。

Java生成Excel文件可参考:Java处理数据导出功能

二、实现思路 需要配置 阿里云oss的 endpoint、key、secret、bucket、folder文件夹 思路:将后端生成的文件 存至本地目录下的临时文件夹中(./localFolder),然后执行上传方法,上传成功后,删除本地临时文件夹中的文件,返回OSS中的文件下载地址即可。

/**
* 上传文件
* @param fileName 文件名
* @param workbook 生成的Excel流
* @return 上传文件地址
* @throws IOException
*/
public String getFileUrl(String fileName, Workbook workbook) throws IOException {
    // 将文件写入本地文件夹
    String filePath = "."+ File.separator + orderFolder;
    File dir = new File(filePath);
    if (!dir.exists()) {
        dir.mkdir();
        log.info("orderFolder 文件夹创建完毕!");
    }
    String filePathName = filePath + File.separator + fileName;
    FileOutputStream output = new FileOutputStream(filePathName);
    workbook.write(output);//写入磁盘
    output.close();
    log.info("文件已存入!");


    // 如果文件写入成功,则上传至 OSS
    File file = new File(filePathName);
    String fileUrl = "";
    if (file.exists()) {
        fileUrl = ossUtil.UploadFile(file, fileName);
    }


    // 上传成功后,删除本地文件
    if (AirUtils.hv(fileUrl)) {
        file.delete();
    }
    System.out.println("下载地址:" + fileUrl);
    return fileUrl;
}
/**
* 上传文件
* @param fileName 文件名
* @param bytes 生成的Excel字节
* @return 上传文件地址
* @throws IOException
*/
public String getFileUrl(String fileName, byte[] bytes) throws IOException {
    // 将文件写入本地文件夹
    String filePath = "."+ File.separator + orderFolder;
    File dir = new File(filePath);
    if (!dir.exists()) {
        dir.mkdir();
        log.info("orderFolder 文件夹创建完毕!");
    }
    String filePathName = filePath + File.separator + fileName;
    FileOutputStream output = new FileOutputStream(filePathName);
    output.write(bytes);//写入磁盘
    output.close();
    log.info("文件已存入!");

    // 如果文件写入成功,则上传至 OSS
    File file = new File(filePathName);
    String fileUrl = "";
    if (file.exists()) {
        fileUrl = ossUtil.UploadFile(file, fileName);
    }
    // 上传成功后,删除本地文件
    if (AirUtils.hv(fileUrl)) {
        file.delete();
    }
    System.out.println("下载地址:" + fileUrl);
    return fileUrl;
}


/**
* 上传Excel文件
* @param file
* @return
*/
public String UploadFile(File file, String localFileName) {
    try {
        // Endpoint以杭州为例,其它Region请按实际情况填写。
        String endpoint = "http://"+ossProperies.getDomain();
        // 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建RAM账号。
        String accessKeyId = ossProperies.getKey();
        String accessKeySecret = ossProperies.getSecret();
        // 创建OSSClient实例。
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);


        // 上传文件
        String fileName = ossProperies.getFolderOrder() + "/" + localFileName;
        ossClient.putObject(ossProperies.getBucket(), fileName, file);


        // 关闭OSSClient。
        ossClient.shutdown();
        return "http://"+ossProperies.getBucket()+"."+ossProperies.getDomain()+"/"+fileName;


    }catch (Exception e){
        logger.error("oss上传失败",e);
        return null;
    }
}