javax.imageio.ImageIO.read(new URL(str_uri))出错, 参考

本文讨论了使用javax.imageio.ImageIO.read方法从URL读取图片时可能遇到的问题,特别是当URL构建不正确时导致的错误。文章提供了一些个人见解和建议,帮助读者检查并修正URL构建中的常见错误。
http://topic.youkuaiyun.com/t/20060709/22/4869573.html#r_achor

老帖不能回答,
2007年之前的帖子暂时不开放该功能!

问题
javax.imageio.ImageIO.read(unknown   source)


请后来人检查自己的url构建是否错误,



即 javax.imageio.ImageIO.read(new   URL(str_uri))出错

比如str 中是否有file:/等内容

个人见解仅供参考
package cn.lk.ehs.module.equipment.service.impl; import cn.lk.ehs.framework.common.pojo.CommonResult; import cn.lk.ehs.framework.mongodb.base.service.impl.LKServiceImpl; import cn.lk.ehs.module.equipment.entity.Record; import cn.lk.ehs.module.equipment.entity.*; import cn.lk.ehs.module.equipment.mapper.FixMapper; import cn.lk.ehs.module.equipment.service.*; import cn.lk.ehs.module.equipment.utils.TaxUtil; import lombok.extern.slf4j.Slf4j; import org.apache.poi.util.Units; import org.apache.poi.wp.usermodel.HeaderFooterType; import org.apache.poi.xwpf.usermodel.*; import org.openxmlformats.schemas.wordprocessingml.x2006.main.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.stereotype.Service; import javax.imageio.IIOImage; import javax.imageio.ImageIO; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.stream.ImageOutputStream; import java.awt.*; import java.awt.image.BufferedImage; import java.io.*; import java.math.BigDecimal; import java.math.BigInteger; import java.net.URL; import java.net.URLConnection; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; import static cn.lk.ehs.framework.common.pojo.CommonResult.error; import static cn.lk.ehs.framework.common.pojo.CommonResult.success; @Slf4j @Service public class FixDetailServiceImpl extends LKServiceImpl<FixMapper, FixDetail, String> implements FixDetailService { @Autowired private EquipmentService equipmentService; @Autowired private EntityService entityService; @Autowired private ConstructService constructService; @Autowired private ShareService shareService; @Autowired private cn.lk.ehs.module.equipment.service.LedgerService ledgerService; @Autowired private RecordService recordService; @Autowired private PartService partService; @Value("${file.upload.base-path}") private String basePath; private static final int BATCH_SIZE = 100; // 分批处理大小 private static final int PAGE_SIZE_LIMIT = 4; // 每页最大行数 private static final int MAX_IMAGE_SIZE_KB = 100; // 目标图片大小 @Override public CommonResult addFixDetail(FixDetail itemData) { //验证项目是否可以转固 Query query = Query.query(Criteria.where("itemNum").is(itemData.getItemNum())); query.addCriteria(Criteria.where("deleted").is(0)); List<EquipmentData> equipmentData = equipmentService.list(query); if (!equipmentData.isEmpty()) { if (!"1".equals(equipmentData.get(0).getIsAccept())) { return error(1, "项目未完成验收无法转固!"); } //查数据补入台账表 List<EntityItem> entityItems = entityService.getlist(query, itemData.getItemNum()); List<Construct> constructs = constructService.list(query); //做一个台账对象插入数据库 更改项目表状态 List<Ledger> ledgers = packageLedger(entityItems, equipmentData, constructs); ledgerService.saveBatch(ledgers); EquipmentData e = equipmentData.get(0); e.setFixedDate(itemData.getDate()); e.setIsFixed("1"); e.setStatus(6); e.setItemType("5"); equipmentService.updateById(e); List<Record> records = packageRecords(itemData, e); recordService.saveBatch(records); save(itemData); } else { return error(1, "未查询到合同信息!"); } return success(itemData); } /** * 拼装档案数据 * * @param itemData * @param e * @return */ private List<Record> packageRecords(FixDetail itemData, EquipmentData e) { List<Record> records = new ArrayList<>(); for (int i = 0; i < 5; i++) { Record record = new Record(); record.setItemNum(itemData.getItemNum()); record.setItemName(e.getItemName()); record.setContractNum(e.getContractNum()); record.setSupplierName(e.getSupplierName()); record.setSupplierCode(e.getSupplierCode()); switch (i) { case 0: record.setType("5"); record.setFileUri(itemData.getCheckFixUri()); if (!itemData.getCheckFixUri().isEmpty()) { records.add(record); } break; case 1: record.setType("6"); record.setFileUri(itemData.getVerifyUri()); if (!itemData.getVerifyUri().isEmpty()) { records.add(record); } break; case 2: record.setType("7"); record.setFileUri(itemData.getPromiseUri()); if (!itemData.getPromiseUri().isEmpty()) { records.add(record); } break; case 3: record.setType("9"); record.setFileUri(itemData.getEntityUri()); if (!itemData.getEntityUri().isEmpty()) { records.add(record); } break; case 4: record.setType("10"); record.setFileUri(itemData.getDrawingUri()); if (!itemData.getDrawingUri().isEmpty()) { records.add(record); } break; default: break; } } List<FileRecords> otherUris = itemData.getOtherUri(); if (!otherUris.isEmpty()) { //先查询是否有同项目编号 项目名 合同号的数据 Query entityQuery = Query.query(Criteria.where("itemNum").is(itemData.getItemNum())); entityQuery.addCriteria(Criteria.where("itemName").is(e.getItemName())); entityQuery.addCriteria(Criteria.where("contractNum").is(e.getContractNum())); entityQuery.addCriteria(Criteria.where("type").is(0)); List<Record> existRecord = recordService.list(entityQuery); if (!existRecord.isEmpty()) { List<FileRecords> urls = existRecord.get(0).getFileUri(); urls.addAll(otherUris); records.get(0).setFileUri(urls); recordService.updateById(records.get(0)); } else { Record record = new Record(); record.setItemNum(itemData.getItemNum()); record.setItemName(e.getItemName()); record.setContractNum(e.getContractNum()); record.setType("0"); record.setFileUri(otherUris); record.setSupplierName(e.getSupplierName()); record.setSupplierCode(e.getSupplierCode()); recordService.save(record); } } return records; } private List<Ledger> packageLedger(List<EntityItem> entityItems, List<EquipmentData> equipmentData, List<Construct> constructs) { List<Ledger> ledgers = new ArrayList<>(); EquipmentData itemData = equipmentData.get(0); for (EntityItem entityItem : entityItems) { //查询toolNumber在台账表内是否存在 如果已经存在把比例改为百分之百 Query ledQuery = Query.query(Criteria.where("toolNumber").is(entityItem.getToolNumber())); ledQuery.addCriteria(Criteria.where("deleted").is(0)); List<Ledger> ledgerList = ledgerService.list(ledQuery); if (null != ledgerList && !ledgerList.isEmpty()) { Ledger ledger = ledgerList.get(0); ledger.setFinishRatio("100%"); ledgerService.updateById(ledger); continue; } Ledger ledger = new Ledger(); //,模具部分 ledger.setToolNumber(entityItem.getToolNumber()); ledger.setToolName(entityItem.getToolName()); ledger.setNameplateUri(getNameplate(entityItem.getItemNum(), entityItem.getToolNumber())); ledger.setToolUri(getToolUri(entityItem.getItemNum(), entityItem.getToolNumber())); ledger.setProductUri(getProductUri(entityItem.getItemNum(), entityItem.getToolNumber())); ledger.setNum(entityItem.getNum()); ledger.setCarModule(entityItem.getCarModule().stream().collect(Collectors.joining("/"))); ledger.setAssetType(entityItem.getAssetType()); ledger.setNewOrOld(entityItem.getNewOrOld()); ledger.setCavitiesNum(entityItem.getCavitiesNum()); ledger.setMaterial(entityItem.getMaterial()); ledger.setSize(entityItem.getSize()); ledger.setWeight(entityItem.getWeight()); ledger.setSapCode(entityItem.getSapCode()); //新增字段 //项目部分 ledger.setItemNum(itemData.getItemNum()); ledger.setItemName(itemData.getItemName()); ledger.setContractNum(itemData.getContractNum()); ledger.setSupplierCode(itemData.getSupplierCode()); ledger.setSupplierName(itemData.getSupplierName()); //零件部分。 Query query = Query.query(Criteria.where("itemNum").is(itemData.getItemNum())); query.addCriteria(Criteria.where("deleted").is(0)); query.addCriteria(Criteria.where("toolNumber").is(entityItem.getToolNumber())); //新增BUG,按单个资产查询零件。 List<PartItem> partItems = partService.list(query); //将零件编号和零件名称组合写入台账 String partCodes = partItems.stream().map(PartItem::getPartCode).collect(Collectors.joining("/")); String partNames = partItems.stream().map(PartItem::getPartName).collect(Collectors.joining("/")); ledger.setParCodes(partCodes); ledger.setParNames(partNames); ledger.setConstructList(constructs); ledger.setIsShare("0"); //判断是否包含分摊。如果包含分摊 归拢出当前模具对总价值的占比 if (null != itemData.getProjectType() && "在建".equals(itemData.getProjectType()) && null != itemData.getLinkContract() && !itemData.getLinkContract().isEmpty()) { ledger.setIsShare("1"); // ledger.setShareTax(itemData.getFixedRatio()); ledger.setFixedRatio(itemData.getFixedRatio()); ledger.setFinishRatio(TaxUtil.calculatePartyBOwnership(itemData.getFixedRatio())); } if (null != itemData.getProjectType() && "分摊".equals(itemData.getProjectType())) { ledger.setIsShare("1"); // ledger.setShareTax(itemData.getFixedRatio()); ledger.setFixedRatio(itemData.getFixedRatio()); ledger.setFinishRatio(itemData.getFixedRatio() + "%"); } ledger.setSecondary("0"); //资产 ledger.setAssetsSubord(entityItem.getSapCode() + "0"); //资产加次级 ledger.setEntityDesc(entityItem.getToolName()); //资产描述 ledger.setCapitalizationDate(""); ledger.setPurchasePrice(entityItem.getTaxMoney()); ledger.setImpairmentAmount(""); ledger.setBookValue(""); ledger.setCurrency(""); ledger.setCostCenter(""); ledger.setAssetClass(""); ledger.setSubject(""); ledger.setStockCode(entityItem.getToolNumber()); //存货号 ledger.setStatus("1"); //资产状态 ledger.setCategory(parseCatgory(entityItem.getNewOrOld())); //资产类别 if (itemData.getSupplierName().equals(entityItem.getLocation())) { ledger.setPrimaryLocation(itemData.getSupplierName()); //一级存放地点 ledger.setSecondaryLocation(""); //二级存放地点 } else { ledger.setPrimaryLocation(itemData.getSupplierName()); //一级存放地点 ledger.setSecondaryLocation(entityItem.getLocation()); //二级存放地点 } ledger.setLife(entityItem.getModelLife()); //设计寿命 ledgers.add(ledger); } return ledgers; } private String parseCatgory(Object cellValue) { //对象属性转CellData if (cellValue == null) { return ""; } if (cellValue.equals("新制")) { return "1"; } else if (cellValue.equals("改制")) { return "2"; } return "1"; } private List<String> getToolUri(String ItemNum, String toolNumber) { Query entityQuery = Query.query(Criteria.where("itemNum").is(ItemNum)); entityQuery.addCriteria(Criteria.where("deleted").is(0)); entityQuery.addCriteria(Criteria.where("toolNumber").is(toolNumber)); List<EntityItem> entityItems = entityService.list(entityQuery); for (EntityItem fixTool : entityItems) { if (toolNumber.equals(fixTool.getToolNumber())) { List<FileRecords> files = fixTool.getPropertyUri(); if (files.size() > 0) { return files.stream().map(FileRecords::getFileUri).collect(Collectors.toList()); } } } return new ArrayList<String>(); } private List<String> getProductUri(String ItemNum, String toolNumber) { Query entityQuery = Query.query(Criteria.where("itemNum").is(ItemNum)); entityQuery.addCriteria(Criteria.where("deleted").is(0)); entityQuery.addCriteria(Criteria.where("toolNumber").is(toolNumber)); List<EntityItem> entityItems = entityService.list(entityQuery); for (EntityItem fixTool : entityItems) { if (toolNumber.equals(fixTool.getToolNumber())) { List<FileRecords> files = fixTool.getProductUri(); if (files.size() > 0) { return files.stream().map(FileRecords::getFileUri).collect(Collectors.toList()); } } } return new ArrayList<String>(); } private String getNameplate(String ItemNum, String toolNumber) { Query entityQuery = Query.query(Criteria.where("itemNum").is(ItemNum)); entityQuery.addCriteria(Criteria.where("deleted").is(0)); entityQuery.addCriteria(Criteria.where("toolNumber").is(toolNumber)); List<EntityItem> entityItems = entityService.list(entityQuery); for (EntityItem fixTool : entityItems) { if (toolNumber.equals(fixTool.getToolNumber())) { List<FileRecords> files = fixTool.getNameplateUri(); if (files.size() > 0) { return files.get(0).getFileUri(); } } } return ""; } /** * 获取当前模具下零件的付款总额 * * @return */ private String getPartTax(List<PartItem> partItems, EquipmentData itemData, List<Construct> constructs) { partItems = packagePart(partItems); BigDecimal total = new BigDecimal("0.00"); for (PartItem item : partItems) { if (item.getAlreadyNum().isBlank() || item.getPrice().isBlank()) { continue; } BigDecimal alreadyNum = new BigDecimal(item.getAlreadyNum().trim()); BigDecimal price = new BigDecimal(item.getPrice().trim()); BigDecimal partSum = alreadyNum.multiply(price); total = total.add(partSum); } Query query = Query.query(Criteria.where("itemNum").is(itemData.getItemNum())); query.addCriteria(Criteria.where("deleted").is(0)); BigDecimal constructTotal = new BigDecimal("0.00"); for (Construct item : constructs) { BigDecimal part = new BigDecimal(item.getPayNum().trim()); constructTotal = constructTotal.add(part); } BigDecimal amount = new BigDecimal(itemData.getAmount()); // 格式化为两位小数 DecimalFormat df = new DecimalFormat("0.00"); return TaxUtil.calculatePercentage(amount.subtract(constructTotal).toString(), df.format(total)); } /** * 拼装已收货数量为了后边算总价做准备 * * @param partItems * @return */ private List<PartItem> packagePart(List<PartItem> partItems) { if (partItems.isEmpty()) { return partItems; } for (PartItem partItem : partItems) { //循环零件表数据 去到货表内拿子数据 Query query = Query.query(Criteria.where("partId").is(partItem.getId())); query.addCriteria(Criteria.where("deleted").is(0)); query.addCriteria(Criteria.where("partCode").is(partItem.getPartCode())); List<ShareItem> list = shareService.list(query); int sum = list.stream() .filter(Objects::nonNull) // 过滤 null 值 .mapToInt(ShareItem::getNum) .sum(); partItem.setAlreadyNum(String.valueOf(sum)); } return partItems; } @Override public CommonResult uptFixDetail(FixDetail itemData) { //验证项目是否可以转固 Query query = Query.query(Criteria.where("itemNum").is(itemData.getItemNum())); query.addCriteria(Criteria.where("deleted").is(0)); query.addCriteria(Criteria.where("status").is(5)); List<EquipmentData> finance = equipmentService.list(query); if (!finance.isEmpty()) { itemData.setFinanceStatus(0); updateById(itemData); } else { return error(1, "项目未处于待转固状态!"); } return success(itemData); } @Override public ByteArrayOutputStream exportToWord(List<EntityItem> entityItems) throws Exception { return exportToWordStream(entityItems); } public ByteArrayOutputStream exportToWordStream(List<EntityItem> records) throws Exception { // 创建临时文件作为缓冲区 File tempFile = File.createTempFile("word_export", ".docx"); try (FileOutputStream fos = new FileOutputStream(tempFile); XWPFDocument doc = new XWPFDocument()) { // 设置页面布局 setupPageLayout(doc); // 初始化表格和计数器 XWPFTable currentTable = createNewTable(doc); int currentPageRowCount = 1; int num = 0; // 处理所有记录 for (int i = 0; i < records.size(); i++) { EntityItem record = records.get(i); // 分批处理:定期写入磁盘释放内存 if (i > 0 && i % BATCH_SIZE == 0) { doc.write(fos); fos.flush(); doc.removeBodyElement(doc.getPosOfTable(currentTable)); currentTable = createNewTable(doc); } // 计算图片行数 int maxImageRows = calculateMaxImageRows( record.getPropertyUri(), record.getNameplateUri(), record.getProductUri() ); // 分页检查 if (currentPageRowCount + maxImageRows > PAGE_SIZE_LIMIT) { doc.createParagraph().setPageBreak(true); currentTable = createNewTable(doc); currentPageRowCount = 1; } // 创建数据行 XWPFTableRow row = currentTable.createRow(); row.setCantSplitRow(true); // 文本列 createFixedWidthTextCell(row, 0, String.valueOf(++num), 800); createFixedWidthTextCell(row, 1, record.getToolNumber(), 1000); createFixedWidthTextCell(row, 2, record.getToolName(), 1000); // 图片列(使用流式处理) addImagesToCellWithStream(row.getCell(3), record.getPropertyUri(), 6800, 2, 1); addImagesToCellWithStream(row.getCell(4), record.getNameplateUri(), 3000, 1, 2); addImagesToCellWithStream(row.getCell(5), record.getProductUri(), 3000, 2, 3); currentPageRowCount += maxImageRows; } // 添加页码并写入最终内容 addPageNumbers(doc); doc.write(fos); // 从临时文件读取到字节流 return readTempFileToOutputStream(tempFile); } finally { // 确保删除临时文件 if (tempFile.exists()) { tempFile.delete(); } } } // 读取临时文件到字节流 private ByteArrayOutputStream readTempFileToOutputStream(File tempFile) throws IOException { try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); FileInputStream fis = new FileInputStream(tempFile)) { byte[] buffer = new byte[1024]; int len; while ((len = fis.read(buffer)) > 0) { outputStream.write(buffer, 0, len); } return outputStream; } } // 统一表格创建方法 private XWPFTable createNewTable(XWPFDocument doc) { XWPFTable table = doc.createTable(); setupTable(table); createTableHeader(table); return table; } // 优化图片行数计算 private int calculateMaxImageRows(List<FileRecords>... imageLists) { int maxRows = 0; for (List<FileRecords> list : imageLists) { if (list != null && !list.isEmpty()) { int itemCount = list.size(); int cols = (list == imageLists[2]) ? 4 : 2; // 产品图4列,其它2列 int rows = (int) Math.ceil((double) itemCount / cols); maxRows = Math.max(maxRows, rows); } } return maxRows > 0 ? maxRows : 1; // 至少1行 } // 页面设置 private static void setupPageLayout(XWPFDocument doc) { CTSectPr sectPr = doc.getDocument().getBody().addNewSectPr(); CTPageSz pageSize = sectPr.addNewPgSz(); pageSize.setOrient(STPageOrientation.LANDSCAPE); pageSize.setW(BigInteger.valueOf(16840)); pageSize.setH(BigInteger.valueOf(11900)); CTPageMar pageMar = sectPr.addNewPgMar(); pageMar.setLeft(BigInteger.valueOf(390)); pageMar.setRight(BigInteger.valueOf(390)); pageMar.setTop(BigInteger.valueOf(900)); pageMar.setBottom(BigInteger.valueOf(900)); pageMar.setFooter(BigInteger.valueOf(900)); } // 表格设置 private static void setupTable(XWPFTable table) { table.setWidth("100%"); int[] columnWidths = {500, 500, 500, 5000, 2000, 5000}; CTTbl cttbl = table.getCTTbl(); CTTblGrid tblGrid = cttbl.getTblGrid() != null ? cttbl.getTblGrid() : cttbl.addNewTblGrid(); // 清空现有网格列 if (tblGrid.sizeOfGridColArray() > 0) { tblGrid.removeGridCol(0); } // 添加新网格列 for (int width : columnWidths) { CTTblGridCol gridCol = tblGrid.addNewGridCol(); gridCol.setW(BigInteger.valueOf(width)); } } // 创建表头 private static void createTableHeader(XWPFTable table) { XWPFTableRow headerRow = table.getRow(0); for (int i = 0; i < 6; i++) { XWPFTableCell cell = headerRow.getCell(i) != null ? headerRow.getCell(i) : headerRow.createCell(); // 清除现有内容 for (int j = cell.getParagraphs().size() - 1; j >= 0; j--) { cell.removeParagraph(j); } // 添加新内容 XWPFParagraph para = cell.addParagraph(); para.setAlignment(ParagraphAlignment.CENTER); XWPFRun run = para.createRun(); run.setBold(true); run.setFontSize(12); run.setText(getHeaderText(i)); } } // 固定宽度文本单元格 private void createFixedWidthTextCell(XWPFTableRow row, int pos, String text, int width) { XWPFTableCell cell = row.getCell(pos) != null ? row.getCell(pos) : row.createCell(); // 清除现有内容 for (int i = cell.getParagraphs().size() - 1; i >= 0; i--) { cell.removeParagraph(i); } // 设置固定宽度 CTTcPr tcPr = cell.getCTTc().getTcPr(); if (tcPr == null) tcPr = cell.getCTTc().addNewTcPr(); tcPr.addNewTcW().setW(BigInteger.valueOf(width)); // 添加内容 XWPFParagraph para = cell.addParagraph(); para.setAlignment(ParagraphAlignment.CENTER); para.setWordWrap(true); XWPFRun run = para.createRun(); run.setText(text); } // 图片流获取方法 private InputStream getImageStream(String uri) throws IOException { URL url = new URL(uri); URLConnection conn = url.openConnection(); conn.setConnectTimeout(5000); conn.setReadTimeout(10000); return conn.getInputStream(); } // 图片尺寸计算 private int[] calculateImageDimensions(int flags) { switch (flags) { case 1: return new int[]{135, 120}; // 属性图 case 2: return new int[]{245, 120}; // 铭牌 case 3: return new int[]{60, 60}; // 产品图 default: return new int[]{120, 120};// 默认 } } // 表头文本 private static String getHeaderText(int colIndex) { String[] headers = {"序号", "工装编号", "资产名称", "关联图片", "铭牌", "产品图片"}; return colIndex < headers.length ? headers[colIndex] : ""; } // 添加页码 private static void addPageNumbers(XWPFDocument doc) { XWPFFooter footer = doc.createFooter(HeaderFooterType.DEFAULT); XWPFParagraph para = footer.createParagraph(); para.setAlignment(ParagraphAlignment.CENTER); XWPFRun run = para.createRun(); run.getCTR().addNewFldChar().setFldCharType(STFldCharType.BEGIN); run.getCTR().addNewInstrText().setStringValue("PAGE"); run.getCTR().addNewFldChar().setFldCharType(STFldCharType.END); run.setText(" / "); run.getCTR().addNewFldChar().setFldCharType(STFldCharType.BEGIN); run.getCTR().addNewInstrText().setStringValue("NUMPAGES"); run.getCTR().addNewFldChar().setFldCharType(STFldCharType.END); } // 图片类型检测 private int determineImageType(String fileName) { if (fileName == null || fileName.lastIndexOf(".") == -1) { return XWPFDocument.PICTURE_TYPE_PNG; // 默认PNG } String ext = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase(); switch (ext) { case "png": return XWPFDocument.PICTURE_TYPE_PNG; case "jpg": case "jpeg": return XWPFDocument.PICTURE_TYPE_JPEG; case "gif": return XWPFDocument.PICTURE_TYPE_GIF; case "bmp": return XWPFDocument.PICTURE_TYPE_BMP; default: return XWPFDocument.PICTURE_TYPE_PNG; } } // 修改图片处理方法 private void addImagesToCellWithStream(XWPFTableCell cell, List<FileRecords> imagePaths, int cellWidth, int colsPerRow, int flags) { if (cell == null || imagePaths == null || imagePaths.isEmpty()) return; // 清除单元格现有内容 for (int i = cell.getParagraphs().size() - 1; i >= 0; i--) { cell.removeParagraph(i); } // 设置单元格宽度 CTTcPr tcPr = cell.getCTTc().getTcPr(); if (tcPr == null) tcPr = cell.getCTTc().addNewTcPr(); tcPr.addNewTcW().setW(BigInteger.valueOf(cellWidth)); XWPFParagraph currentPara = cell.addParagraph(); currentPara.setAlignment(ParagraphAlignment.LEFT); XWPFRun currentRun = currentPara.createRun(); for (int i = 0; i < imagePaths.size(); i++) { FileRecords imagePath = imagePaths.get(i); try { // 获取优化后的图片流 try (InputStream is = getOptimizedImageStream(imagePath.getFileUri(), flags)) { if (is != null) { int imageType = determineImageType(imagePath.getFileUri()); int[] dimensions = calculateImageDimensions(flags); // 添加压缩后的图片 currentRun.addPicture( is, imageType, imagePath.getFileUri(), Units.toEMU(dimensions[0]), Units.toEMU(dimensions[1]) ); } } // 换行控制 if ((i + 1) % colsPerRow == 0 && (i + 1) < imagePaths.size()) { currentPara = cell.addParagraph(); currentPara.setAlignment(ParagraphAlignment.LEFT); currentRun = currentPara.createRun(); } } catch (Exception e) { currentRun.setText("[图片处理失败: " + e.getMessage() + "]"); } } } // 图片优化处理 private InputStream getOptimizedImageStream(String uri, int flags) throws IOException { URL url = new URL(uri); URLConnection conn = url.openConnection(); conn.setConnectTimeout(5000); conn.setReadTimeout(10000); try (InputStream originalStream = conn.getInputStream()) { // 获取原始图片 BufferedImage originalImage = ImageIO.read(originalStream); if (originalImage == null) return null; // 计算目标尺寸并缩放 int[] targetDimensions = calculateTargetDimensions(originalImage, flags); BufferedImage scaledImage = scaleImage(originalImage, targetDimensions[0], targetDimensions[1]); // 压缩并转换格式 return compressImage(scaledImage, MAX_IMAGE_SIZE_KB * 1024); } } // 计算优化后的尺寸 private int[] calculateTargetDimensions(BufferedImage image, int flags) { int[] displayDims = calculateImageDimensions(flags); int displayWidth = displayDims[0]; int displayHeight = displayDims[1]; // 保持原始宽高比 double aspectRatio = (double) image.getWidth() / image.getHeight(); int targetWidth = displayWidth; int targetHeight = (int) (targetWidth / aspectRatio); // 确保不小于显示尺寸 if (targetHeight < displayHeight) { targetHeight = displayHeight; targetWidth = (int) (targetHeight * aspectRatio); } // 限制最大尺寸(避免过大) int maxDimension = 1500; // 最大像素尺寸 if (targetWidth > maxDimension || targetHeight > maxDimension) { if (targetWidth > targetHeight) { targetWidth = maxDimension; targetHeight = (int) (maxDimension / aspectRatio); } else { targetHeight = maxDimension; targetWidth = (int) (maxDimension * aspectRatio); } } return new int[]{targetWidth, targetHeight}; } // 图片缩放 private BufferedImage scaleImage(BufferedImage original, int width, int height) { BufferedImage scaled = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D g = scaled.createGraphics(); g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g.drawImage(original, 0, 0, width, height, null); g.dispose(); return scaled; } // 图片压缩 private InputStream compressImage(BufferedImage image, long maxSize) throws IOException { float quality = 0.8f; // 初始质量 ByteArrayOutputStream output = new ByteArrayOutputStream(); // 迭代压缩直到满足大小 do { output.reset(); ImageWriter writer = ImageIO.getImageWritersByFormatName("jpg").next(); ImageWriteParam param = writer.getDefaultWriteParam(); // 设置压缩参数 if (param.canWriteCompressed()) { param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); param.setCompressionQuality(quality); } try (ImageOutputStream ios = ImageIO.createImageOutputStream(output)) { writer.setOutput(ios); writer.write(null, new IIOImage(image, null, null), param); } writer.dispose(); quality -= 0.1f; // 降低质量 } while (output.size() > maxSize && quality > 0.3f); // 转换为JPEG格式(更好的压缩率) return new ByteArrayInputStream(output.toByteArray()); } }帮忙整理下代码注释 间隔等等给一份完整代码
09-26
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值