背景
工作中肯定会有导入excel还附带图片附件的
下面是我解析的excel,支持图片、pdf、压缩文件
实现
依次去解析excel,看看也没有附件,返回的格式是Map,key是第几行,value是附件list
附件格式都被解析成pdf格式
Reader.java
package com.ruoyi.srm.service;
import java.util.List;
import org.apache.poi.ss.usermodel.Workbook;
import com.ruoyi.srm.domain.req.CapacityReceivingReq.FileListBean;
public interface Reader {
List<FileListBean> read(Workbook workbook, int targetCol);
}
ReaderComposite.java
package com.ruoyi.srm.service.impl;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.ruoyi.srm.domain.req.CapacityReceivingReq.FileListBean;
import com.ruoyi.srm.service.Reader;
@Component
public class ReaderComposite {
@Autowired
private List<Reader> readerList;
public Map<String, List<FileListBean>> read(Workbook workbook, int targetCol) {
return readerList.stream()
.map(reader -> reader.read(workbook, targetCol))
.flatMap(Collection::stream).collect(Collectors.groupingBy(t -> t.getLine() + ""));
}
}
ImageReader.java
package com.ruoyi.srm.service.impl;
import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFDrawing;
import org.apache.poi.xssf.usermodel.XSSFPicture;
import org.apache.poi.xssf.usermodel.XSSFPictureData;
import org.apache.poi.xssf.usermodel.XSSFShape;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.stereotype.Component;
import com.ruoyi.srm.domain.req.CapacityReceivingReq.FileListBean;
import com.ruoyi.srm.service.Reader;
import cn.hutool.core.io.FileUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Component
public class ImageReader implements Reader {
@Override
@SneakyThrows
public List<FileListBean> read(Workbook workbook, int targetCol) {
ApplicationHome home = new ApplicationHome();
String rootPath = home.getDir().getAbsolutePath() + File.separator + "extract" + File.separator;
List<FileListBean> result = new ArrayList<>();
Map<String, AtomicInteger> counter = new HashMap<>();
Sheet sheet = workbook.getSheetAt(0);
if (sheet instanceof XSSFSheet) {
XSSFSheet xssfSheet = (XSSFSheet) sheet;
XSSFDrawing drawing = xssfSheet.getDrawingPatriarch();
if (drawing != null) {
String dir = rootPath + "_" + System.currentTimeMillis();
for (XSSFShape shape : drawing.getShapes()) {
if (shape instanceof XSSFPicture) {
XSSFPicture picture = (XSSFPicture) shape;
XSSFClientAnchor anchor = (XSSFClientAnchor) picture.getAnchor();
int targetRow = anchor.getRow1();
if (anchor.getCol1() == targetCol) {
AtomicInteger integer = counter.computeIfAbsent(targetRow + "_" + targetCol, k -> new AtomicInteger());
XSSFPictureData pictureData = picture.getPictureData();
byte[] imageBytes = pictureData.getData();
new File(dir).mkdirs();
String filePath = dir + File.separator + "image_" + (targetRow + 1) + "_" + targetCol + "_" + integer
.incrementAndGet() + "." + pictureData
.suggestFileExtension();
try (FileOutputStream out = new FileOutputStream(filePath)) {
out.write(imageBytes);
log.info("第{}行图片已保存到: {}", targetRow + 1, filePath);
String encodeToString = Base64.getEncoder().encodeToString(FileUtil.readBytes(filePath));
String mimeType = FileUtil.getMimeType(filePath);
if ("image/jpeg".equals(mimeType)) {
encodeToString = "data:image/png;base64," + encodeToString;
}
result.add(new FileListBean().setFileName(new File(filePath).getName()).setContent(encodeToString).setLine(targetRow));
}
}
}
}
}
}
return result;
}
}
AttachmentReader.java
package com.ruoyi.srm.service.impl;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.io.IOUtils;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFDrawing;
import org.apache.poi.xssf.usermodel.XSSFObjectData;
import org.apache.poi.xssf.usermodel.XSSFShape;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.tika.Tika;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.stereotype.Component;
import com.ruoyi.srm.domain.req.CapacityReceivingReq.FileListBean;
import com.ruoyi.srm.service.Reader;
import cn.hutool.core.io.FileUtil;
import lombok.Cleanup;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Component
public class AttachmentReader implements Reader {
@Override
@SneakyThrows
public List<FileListBean> read(Workbook workbook, int targetCol) {
ApplicationHome home = new ApplicationHome();
String rootPath = home.getDir().getAbsolutePath() + File.separator + "extract" + File.separator;
List<FileListBean> result = new ArrayList<>();
Map<String, AtomicInteger> counter = new HashMap<>();
Sheet sheet = workbook.getSheetAt(0);
XSSFSheet xssfSheet = (XSSFSheet) sheet;
List<POIXMLDocumentPart> relationList = xssfSheet.getRelations();
for (POIXMLDocumentPart part : relationList) {
if (part instanceof XSSFDrawing) {
XSSFDrawing drawing = (XSSFDrawing) part;
for (XSSFShape shape : drawing.getShapes()) {
if (shape instanceof XSSFObjectData) {
XSSFObjectData objData = (XSSFObjectData) shape;
XSSFClientAnchor anchor = (XSSFClientAnchor) objData.getAnchor();
int targetRow = anchor.getRow1();
if (anchor.getCol1() == targetCol) {
AtomicInteger integer = counter.computeIfAbsent(targetRow + "_" + targetCol, k -> new AtomicInteger());
byte[] objectData = objData.getObjectData();
@Cleanup
POIFSFileSystem poifs = new POIFSFileSystem(new ByteArrayInputStream(objectData));
String symbol = "\u0001Ole10Native";
if (poifs.getRoot().getEntryNames().contains(symbol)) {
InputStream contentStream = poifs.createDocumentInputStream(symbol);
String dir = rootPath + "_" + System.currentTimeMillis();
new File(dir).mkdirs();
String name = "";
byte[] byteArray = IOUtils.toByteArray(contentStream);
Tika tika = new Tika();
String detect = tika.detect(byteArray);
System.err.println(detect);
if ("application/pdf".equals(detect)) {
name = dir + File.separator + "pdf_" + (targetRow + 1) + "_" + targetCol + "_" + integer.incrementAndGet() + ".pdf";
} else if ("application/octet-stream".equals(detect)) {
}
@Cleanup
FileOutputStream out = new FileOutputStream(name);
out.write(byteArray);
log.info("第{}行{}文件保存成功: {}", targetRow + 1, detect, name);
if (name.endsWith(".zip")) {
@Cleanup
ZipArchiveInputStream zis = new ZipArchiveInputStream(new FileInputStream(name));
ZipArchiveEntry entry;
while ((entry = zis.getNextEntry()) != null) {
if (entry.isDirectory()) {
log.warn("是目录");
} else {
File file = new File(dir, entry.getName());
try (FileOutputStream out2 = new FileOutputStream(file)) {
byte[] buffer2 = new byte[1024];
int len;
while ((len = zis.read(buffer2)) > 0) {
out2.write(buffer2, 0, len);
}
}
log.info("第{}提取{}已保存到: {}", targetRow + 1, entry.getName(), file.getAbsolutePath());
}
}
}
Arrays.stream(FileUtil.ls(dir)).forEach(item -> {
extracted(result, targetRow, item);
});
}
}
}
}
}
}
return result;
}
private static void extracted(List<FileListBean> result, int targetRow, File item) {
String path = item.getPath();
String encodeToString = Base64.getEncoder().encodeToString(FileUtil.readBytes(path));
String mimeType = FileUtil.getMimeType(path);
if ("image/jpeg".equals(mimeType)) {
encodeToString = "data:image/png;base64," + encodeToString;
} else {
}
result.add(new FileListBean().setFileName(item.getName()).setContent(encodeToString).setLine(targetRow));
}
}