使用POI的excel导入图片,并将图片上传至fastdfs文件服务器

之前excel导入的都是纯数据,后来BA要求可以导入图片,所以关键在于怎么获取excel中的图片数据,本文参考的文章地址:https://blog.csdn.net/wy123123000/article/details/81330712 。在此感谢大神。
我的POI版本 :poi-3.10.1.jar。

知道获取图片的方法后结合到自己的项目中,前端选择一个excel文件提交后,后端进行解析,判断excel的版本:

public Map<String, PictureData> getPictures(MultipartHttpServletRequest request) {
        MultipartFile uploadFile = request.getFile("file");
        String fileName = uploadFile.getOriginalFilename();
        boolean isXlsx = fileName.contains(".xlsx");
        Map<String, PictureData> map = new HashMap<>();
        try (InputStream is = uploadFile.getInputStream()) {
            Workbook wb;
            // 重点
            if (isXlsx) {
                wb = new XSSFWorkbook(is);
                List<POIXMLDocumentPart> list = ((XSSFSheet) wb.getSheetAt(0)).getRelations();
                for (POIXMLDocumentPart part : list) {
                    if (part instanceof XSSFDrawing) {
                        XSSFDrawing drawing = (XSSFDrawing) part;
                        List<XSSFShape> shapes = drawing.getShapes();
                        for (XSSFShape shape : shapes) {
                            XSSFPicture picture = (XSSFPicture) shape;
                            XSSFClientAnchor anchor = picture.getPreferredSize();
                            CTMarker marker = anchor.getFrom();
                            String key = marker.getRow() + "";
//                            marker.getCol();
                            map.put(key, picture.getPictureData());
                        }
                    }
                }
            } else {
                wb = new HSSFWorkbook(is);
                List<HSSFShape> list = ((HSSFSheet) wb.getSheetAt(0)).getDrawingPatriarch().getChildren();
                for (HSSFShape shape : list) {
                    if (shape instanceof HSSFPicture) {
                        HSSFPicture picture = (HSSFPicture) shape;
                        HSSFClientAnchor cAnchor = (HSSFClientAnchor) picture.getAnchor();
                        PictureData pdata = picture.getPictureData();
                        String key = cAnchor.getRow1() + ""; // 行号(左上角)
//                        cAnchor.getCol1(); //列号(左上角)
                        map.put(key, pdata);
                    }
                }
            }
            return map;
        } catch (Exception e) {
            throw new RuntimeException("图片解析异常", e);
        }
    }

这里HSSFClientAnchor 类获取的是row1或者col1,可以点开源码看下他的构造参数,详情参考https://www.cnblogs.com/1175429393wljblog/p/9809868.html:

// dx1 dy1 起始单元格中的x,y坐标.
//dx2 dy2 结束单元格中的x,y坐标
//col1,row1 指定起始的单元格,下标从0开始
//col2,row2 指定结束的单元格 ,下标从0开始
public HSSFClientAnchor(int dx1, int dy1, int dx2, int dy2, short col1, int row1, short col2, int row2) {...}

使用POI的excel导入图片,并将图片上传至fastdfs文件服务器_第1张图片

注意:一个图片最好缩放在一个单元格内,一行可以多个图片,但map的key 就要变了,要加上列号,此处是一行一个图片。按照习惯, 一行一条数据,所以尽量保持一行的数据和该数据的图片再同一行,或者图片按照数据的顺序单独排列在一个sheet页也可以,保持顺序的目的是解析出来的图片map 能够和 每行数据通过行号进行绑定。
经过本地测试发现,在插入图片时,xlsx默认对图片的压缩率更高,所以图像失真较严重,xls就比较好。当然,可以通过excel设置默认不压缩图片,使用原图。

拿到图片map后就可以遍历每行的数据通过行号作为key拿到图片并上传文件服务器:

PictureData pictureData = pictureDataMap.get(rowId + "");
tring pictureName = xxxx;
String path = fdfsService.uploadFile(pictureData.getData(), pictureName);
// 然后将图片绑定到同行的业务数据
...

可以通过pictureData.getMimeType()获取类型,不过我测试后图片的属性都是image/png,即使原图片是jpg格式。你也可以通过pictureData.suggestFileExtension() 获取建议给你的扩展名,注意可能为空。

你可能感兴趣的:(java笔记)