系统需要将PDF文件由后台直接转为img图片,供前端页面直接展示,不需要用户下载即可预览文件内容。直接转换时如果文件过大,耗时很长,影响用户体验,后调研后使用多线程方式进行,显著加快图片转换速度。
原始版访问:https://blog.csdn.net/wmf_helloWorld/article/details/104051137
1、创建线程池
ExecutorService executorService =
new ThreadPoolExecutor(5, 10, 60L, TimeUnit.SECONDS, new ArrayBlockingQueue(50));
初始化线程池,因系统默认一次预览5张图片,进行分页分步预览,所以设置核心线程池大小为5.设置最后队列为new ArrayBlockingQueue(50)),可以排队50个等待任务,若大于50则不建议预览,或根据需要使用其他队列。
可访问:https://www.cnblogs.com/dafanjoy/p/9729358.html
2、主要转换方法体
2.1、全部转换
public List pdfTurnImage(String filePath) throws CodeException {
List fileImageList;
File file = new File(filePath);
try(PDDocument pdDocument = PDDocument.load(file)) {
PdfReader reader = new PdfReader(filePath);
int pages = reader.getNumberOfPages();
LOGGER.info(LogType.INFO, "pdf文件共有"+ pages +"页文件");
String[] imgStrArr = new String[pages];
fileImageList = Arrays.asList(imgStrArr);
List> futureTaskList =new ArrayList<>();
for(int i=0; i future : futureTaskList) {
if(future.get()) {
future.cancel(true);
}
}
} catch (Exception e) {
LOGGER.error(LogType.ERROR, e);
throw new CodeException(XYRFileServerConstants.ERROR_CODE_2017, XYRFileServerConstants.ERROR_MESSAGE_2017, e);
}
return fileImageList;
}
filePath:文件路径
List
fileImageList :定义固定大小的集合,之后将每个图片放在集合的固定位置,防止转换之后图片放置顺序错误。
2.2,分页转换
public List getFileContent(int start, int numbers, String filePath) throws CodeException {
List fileImageList;
File file = new File(filePath);
int begin = start-1;
try(PDDocument pdDocument = PDDocument.load(file)) {
PdfReader reader = new PdfReader(filePath);
int pages = reader.getNumberOfPages();
LOGGER.info(LogType.INFO, "pdf文件共有"+ pages +"页文件");
String[] imgStrArr = new String[numbers];
fileImageList = Arrays.asList(imgStrArr);
List> futureTaskList =new ArrayList<>();
for(int i=0; i future : futureTaskList) {
if(future.get()) {
future.cancel(true);
}
}
} catch (Exception e) {
LOGGER.error(LogType.ERROR, e);
throw new CodeException(XYRFileServerConstants.ERROR_CODE_2017, XYRFileServerConstants.ERROR_MESSAGE_2017, e);
}
return fileImageList;
}
start:开始页码
numbers:分页转换页数
filePath:文件路径
3、文件预览线程
/**
*
* Modify Information:pdf文件预览
* Author Date Description
* ============ ============= ============================
* wumf 2020年7月1日 create this file
*
*/
public class PdfPreviewTask implements Callable{
private static Loggerx logger = Loggerx.getLogger("system");
/**
* 图片列表
*/
private List imageList;
/**
* 图片存放集合位置
*/
private int listPosition;
/**
* 页码
*/
private int pageNumbers;
/**
* 文件路径
*/
private String filePath;
public PdfPreviewTask(List imageList, int pageNumbers, int listPosition, String filePath) {
this.imageList = imageList;
this.listPosition = listPosition;
this.pageNumbers = pageNumbers;
this.filePath = filePath;
}
@Override
public Boolean call() throws Exception {
File file = new File(filePath);
try(PDDocument pdDocument = PDDocument.load(file)) {
PDFRenderer renderer = new PDFRenderer(pdDocument);
logger.info(LogType.INFO, TimeUtil.getTimeStamp()+"线程开始执行,转换第"+pageNumbers+"页文件");
BufferedImage image = renderer.renderImageWithDPI(pageNumbers, Integer.parseInt(SystemEnvironment.dpi));
String imageBase64 = base64Image(image);
if (StringUtil.isNotEmpty(imageBase64)) {
if (!imageBase64.startsWith("data:image")) {
imageBase64 = "data:image/jpeg;base64," + imageBase64;
}
imageList.set(listPosition, imageBase64);
}
logger.info(LogType.INFO, TimeUtil.getTimeStamp()+"线程执行结束,转换第"+pageNumbers+"页文件");
return true;
} catch (Exception e) {
logger.error(LogType.ERROR, "线程执行异常结束"+e.getMessage(), e);
}
return false;
}
private static String base64Image(BufferedImage image) throws CodeException {
try(ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
ImageIO.write(image, "png", baos);//写入流中
byte[] bytes = baos.toByteArray();//转换成字节
return new String(Base64.encode(bytes),"UTF-8");
} catch (Exception e) {
throw new CodeException(XYRFileServerConstants.ERROR_CODE_2017, XYRFileServerConstants.ERROR_MESSAGE_2017, e);
}
}
通过初始化线程时的构造方法参数,设置所需的内容。
renderer.renderImageWithDPI(pageNumbers, Integer.parseInt(SystemEnvironment.dpi));为主要转换方法。具体参数百度。转换为base64格式编码则不需要前端进行额外的转换。