美文网首页
通过 POI 将数据库中的数据上传至 OSS 对象存储

通过 POI 将数据库中的数据上传至 OSS 对象存储

作者: luokaiii | 来源:发表于2018-09-29 19:20 被阅读0次

通过 POI 将数据库中的数据上传至 OSS 对象存储

`我爱你,第一句是假的,第二句也是假的。`

表格的具体样式可以参考 第三章

我们以 aliyun 的 OSS 为例上传 上传方法

一、准备工作

第一步:引入 Apache POI 的依赖

<!-- Maven 方式 -->

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>4.0.0</version>
</dependency>
<!-- Gradle 方式 -->

compile group: 'org.apache.poi', name: 'poi', version: '4.0.0'

第二步:引入 JUnit 测试,这里就不做赘述了。

二、讲解测试用例

Test方法

我们先从测试方法着手,再逐步讲解测试中所用到的方法。

@Autowired
private UserService userService;

@Test
public void upload(){
    List<User> users = userService.findAll(); // ①

    final ByteArrayOutputStream stream = exportProjectList(users); // ②

    String uri = uploadWorkbook(stream, "学生数据表.xlsx"); // ③

    System.out.println(uri); // ④
}
  1. 从数据库中取出需要导入 Excel 的数据
  2. 方法:exportProjectList 将数据存入 POI 生成的 Excel 中,并将 Excel 转换为字节流,用来向对象存储中上传
  3. 方法:uploadWorkbook 上传流式文件,和文件名称
  4. 输出 aliyun 返回的地址,用于业务的实现,比如 保存至数据库 等。

exportProjectList方法

作用:接收从数据库查询出来的对象集合,将其插入到 Workbook 中,并生成二进制的输出流 ByteArrayOutputStream

表格的具体样式可以参考 第三章

private ByteArrayOutputStream exportProjectList(User[] users) throws IOException {
        // Workbook 工作区
        final XSSFWorkbook workbook = new XSSFWorkbook();

        // 单字体居中样式
        final XSSFCellStyle centerStyle = workbook.createCellStyle();
        centerStyle.setAlignment(HorizontalAlignment.CENTER);

        // 字体居中加粗样式
        final XSSFCellStyle headerStyle = workbook.createCellStyle();
        headerStyle.setAlignment(HorizontalAlignment.CENTER);

        final XSSFFont font = workbook.createFont();
        font.setBold(true);
        headerStyle.setFont(font);

        // Sheet 分页
        final XSSFSheet sheet = workbook.createSheet("Sheet Name");

        final String[] strings = new String[]{"序号", "学号", "姓名", "年龄", "院系", "班级"};

        // 首行内容填充,以及设置样式
        setFirstRow(sheet, strings, headerStyle);

        int rowSign = 0;
        for (user user : users) {

            // Row 行
            final XSSFRow row = sheet.createRow(++rowSign);

            // Cell 单元格
            final XSSFCell firstCell = row.createCell(0);
            firstCell.setCellValue(rowSign);
            firstCell.setCellStyle(centerStyle);

            final XSSFCell secondCell = row.createCell(1);
            secondCell.setCellValue(user.getStuNo());
            secondCell.setCellStyle(centerStyle);

            final XSSFCell thirdCell = row.createCell(2);
            thirdCell.setCellValue(user.getName());
            thirdCell.setCellStyle(centerStyle);

            final XSSFCell fourthCell = row.createCell(3);
            fourthCell.setCellValue(user.getAge());
            fourthCell.setCellStyle(centerStyle);

            final XSSFCell fifthCell = row.createCell(4);
            fifthCell.setCellValue(user.getCollege());
            fifthCell.setCellStyle(centerStyle);

            final XSSFCell sixthCell = row.createCell(5);
            sixthCell.setCellValue(user.getClass());
            sixthCell.setCellStyle(centerStyle);
        }

        // 宽度自适应
        for (int s = 0; s < strings.length; s++) {
            sheet.autoSizeColumn(s);
            sheet.setColumnWidth(s, sheet.getColumnWidth(s) * 17 / 10);
        }

        final ByteArrayOutputStream stream = new ByteArrayOutputStream();

        workbook.write(stream);

        return stream;
    }

需要注意的是,每一个单元格 (Cell) 都是不能为空的

我们将设置头标题的方法抽离出来,可供其他设置的方法使用。

/**
 * 设置第一行的头标题
 */
private void setFirstRow(Sheet sheet, String[] cellTitles, XSSFCellStyle headerStyle) {
    final Row row = sheet.createRow(0);

    int cellSign = 0;

    for (String cellName : cellTitles) {
        final Cell cell = row.createCell(cellSign++);
        cell.setCellValue(cellName);
        cell.setCellStyle(headerStyle);
    }
}

在做完前面的工作之后,我们就可以开始写测试方法了

uploadWorkbook方法

该方法用于:接收 Workbook 生成的流,并将其保存至 OSS 上,本方法适用于 aliyunOSS 对象存储,其他的具体实现都可以从官方API中查到。

private String uploadWorkbook(ByteArrayOutputStream stream, String fileId) throws IOException {
    final ByteArrayInputStream inputStream = new ByteArrayInputStream(stream.toByteArray()); // ①

    ObjectMetadata objectMetadata = new ObjectMetadata();
    objectMetadata.setContentLength(stream.size());
    objectMetadata.setContentEncoding("utf-8");
    objectMetadata.setCacheControl("no-cache");
    objectMetadata.setHeader("Pragma", "no-cache");
    objectMetadata.setContentDisposition("inline;filename=" + "学生表数据.xlsx"); // ②

    return ossCore.uploadByStream(fileId, objectMetadata, inputStream); // ③
}
  1. 将输出流转换为输入流
  2. 保存对象的媒体信息
  3. 上传至 aliyunOSS 对象存储,具体实现可以看 第四部分

三、设置Excel单元格样式

创建sheet

HSSFCellStyle cellStyle = wb.createCellStyle();  

一、设置背景色:

cellStyle.setFillForegroundColor((short) 13);// 设置背景色  
cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);  

二、设置边框:

cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN); //下边框  
cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);//左边框  
cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);//上边框  
cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);//右边框  

三、设置居中:

cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 居中  

四、设置字体:

HSSFFont font = wb.createFont();  
font.setFontName("黑体");  
font.setFontHeightInPoints((short) 16);//设置字体大小  
  
HSSFFont font2 = wb.createFont();  
font2.setFontName("仿宋_GB2312");  
font2.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);//粗体显示  
font2.setFontHeightInPoints((short) 12);  
  
cellStyle.setFont(font);//选择需要用到的字体格式  

五、设置列宽:

sheet.setColumnWidth(0, 3766); //第一个参数代表列id(从0开始),第2个参数代表宽度值  参考 :"2012-08-10"的宽度为2500  

六、设置自动换行:

cellStyle.setWrapText(true);//设置自动换行  

七、合并单元格:

Region region1 = new Region(0, (short) 0, 0, (short) 6);//参数1:行号 参数2:起始列号 参数3:行号 参数4:终止列号
//此方法在POI3.8中已经被废弃,建议使用下面一个  
或者用

CellRangeAddress region1 = new CellRangeAddress(rowNumber, rowNumber, (short) 0, (short) 11);

//参数1:起始行 参数2:终止行 参数3:起始列 参数4:终止列
但应注意两个构造方法的参数不是一样的,具体使用哪个取决于POI的不同版本。


sheet.addMergedRegion(region1);

四、上传至OSS等对象存储

作用:上传 stream流 至 OSS

public String uploadByStream(String fileId, ObjectMetadata metadata, InputStream in) {
        String ossUrl = null;
        OSSClient ossClient = new OSSClient(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
        ossClientMap.put(fileId, ossClient);
        try {
            putUploadProgress(fileId, 0);
            PutObjectRequest req = new PutObjectRequest(OssConnectionUtil.getBucketName(), fileId, in, metadata);
            req.setProgressListener(new UploadProgressListener(req));
            PutObjectResult putResult = ossClient.putObject(req);
            if (putResult.getETag() != null) {
                ossUrl =  getOssURL(ossClient, fileId);
            }
            return ossUrl;
        } catch(ClientException ce) {
            return null;
        } catch (Exception e) {
            return null;
        } finally {
            ossClient.shutdown();
            ossClientMap.remove(fileId);
        }
    }

相关文章

网友评论

      本文标题:通过 POI 将数据库中的数据上传至 OSS 对象存储

      本文链接:https://www.haomeiwen.com/subject/dmvboftx.html