使用 Flying-Saucer-Pdf + velocity 模板引擎生成 PDF(处理中文和图片问题)

news/2026/1/17 15:55:38/文章来源:https://www.cnblogs.com/gccbuaa/p/19496323

使用 Flying Saucer Pdf + 模板引擎生成 PDF(解决中文和图片问题)

概述

本文原创(参考自实际项目经验)介绍如何使用Flying Saucer(flying-saucer-pdf)(xhtmlrenderer)结合多种模板引擎(Velocity、FreeMarker、XHTML)生成PDF文件,并解决中文字体显示和图片嵌入问题。

核心技术栈

  1. Flying Saucer (xhtmlrenderer) - 将XHTML转换为PDF
  2. 模板引擎 - 支持Velocity、FreeMarker、原生XHTML
  3. Base64图片编码 - 解决图片嵌入问题

完整解决方案

1. Maven依赖配置

<dependencies><!-- Flying Saucer PDF生成 --><dependency><groupId>org.xhtmlrenderer</groupId><artifactId>flying-saucer-pdf</artifactId><version>9.1.22</version></dependency><!-- Velocity模板引擎 --><dependency><groupId>org.apache.velocity</groupId><artifactId>velocity-engine-core</artifactId><version>2.3</version></dependency><!-- FreeMarker模板引擎 --><dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.32</version></dependency><!-- 工具类 --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.16</version></dependency></dependencies>

2. 通用PDF生成工具类

package com.example.pdf.core;
import com.lowagie.text.pdf.BaseFont;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xhtmlrenderer.pdf.ITextRenderer;
import org.xhtmlrenderer.pdf.ITextUserAgent;
import java.io.*;
import java.util.Map;
/**
* PDF生成核心类(原创实现)
* 解决中文显示和图片嵌入问题
*/
public class PdfGenerator {
private static final Logger log = LoggerFactory.getLogger(PdfGenerator.class);
/**
* 生成PDF文件
* @param htmlContent HTML内容
* @param outputPath 输出文件路径
* @param fontPath 中文字体路径
*/
public static void generatePdf(String htmlContent, String outputPath, String fontPath) {
try (OutputStream os = new FileOutputStream(outputPath)) {
ITextRenderer renderer = new ITextRenderer();
// 设置自定义的ResourceLoader,处理Base64图片
renderer.getSharedContext().setUserAgentCallback(
new CustomResourceLoader()
);
// 设置中文字体
if (fontPath != null && !fontPath.isEmpty()) {
setChineseFont(renderer, fontPath);
}
// 渲染PDF
renderer.setDocumentFromString(htmlContent);
renderer.layout();
renderer.createPDF(os);
log.info("PDF生成成功: {}", outputPath);
} catch (Exception e) {
log.error("PDF生成失败", e);
throw new RuntimeException("PDF生成失败", e);
}
}
/**
* 设置中文字体
*/
private static void setChineseFont(ITextRenderer renderer, String fontPath) throws Exception {
try {
// 尝试加载字体文件
File fontFile = new File(fontPath);
if (fontFile.exists()) {
renderer.getFontResolver().addFont(
fontPath,
BaseFont.IDENTITY_H,
BaseFont.EMBEDDED
);
log.debug("使用字体文件: {}", fontPath);
} else {
// 从classpath加载
InputStream fontStream = PdfGenerator.class
.getClassLoader()
.getResourceAsStream(fontPath);
if (fontStream != null) {
// 创建临时字体文件
File tempFont = File.createTempFile("font_", ".ttc");
try (FileOutputStream fos = new FileOutputStream(tempFont)) {
byte[] buffer = new byte[1024];
int len;
while ((len = fontStream.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
}
renderer.getFontResolver().addFont(
tempFont.getAbsolutePath(),
BaseFont.IDENTITY_H,
BaseFont.EMBEDDED
);
tempFont.deleteOnExit();
log.debug("使用classpath字体: {}", fontPath);
} else {
log.warn("字体文件未找到: {}", fontPath);
}
}
} catch (Exception e) {
log.warn("字体设置失败,使用默认字体", e);
}
}
/**
* 自定义资源加载器,支持Base64图片
*/
private static class CustomResourceLoader extends ITextUserAgent {
@Override
protected InputStream resolveAndOpenStream(String uri) {
// 处理Base64图片
if (uri.startsWith("data:image")) {
try {
// 提取Base64数据
String base64Data = uri.substring(uri.indexOf(",") + 1);
byte[] imageBytes = java.util.Base64.getDecoder().decode(base64Data);
return new ByteArrayInputStream(imageBytes);
} catch (Exception e) {
log.error("Base64图片解析失败", e);
return null;
}
}
return super.resolveAndOpenStream(uri);
}
}
}

3. 模板引擎封装类

package com.example.pdf.template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Map;
/**
* 模板引擎工厂(原创实现)
* 支持Velocity、FreeMarker和原生XHTML
*/
public class TemplateEngine {
/**
* Velocity模板引擎
*/
public static class VelocityRenderer {
private final VelocityEngine velocityEngine;
public VelocityRenderer() {
velocityEngine = new VelocityEngine();
velocityEngine.setProperty("resource.loader", "class");
velocityEngine.setProperty("class.resource.loader.class",
"org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
velocityEngine.setProperty("input.encoding", "UTF-8");
velocityEngine.setProperty("output.encoding", "UTF-8");
velocityEngine.init();
}
public String render(String templatePath, Map<String, Object> data) throws Exception {VelocityContext context = new VelocityContext();if (data != null) {data.forEach(context::put);}String templateContent = loadTemplate(templatePath);StringWriter writer = new StringWriter();velocityEngine.evaluate(context, writer, "template", templateContent);return writer.toString();}}/*** FreeMarker模板引擎*/public static class FreeMarkerRenderer {private final Configuration configuration;public FreeMarkerRenderer(String templateDirectory) throws IOException {configuration = new Configuration(Configuration.VERSION_2_3_32);configuration.setDirectoryForTemplateLoading(new File(templateDirectory));configuration.setDefaultEncoding("UTF-8");}public String render(String templateName, Map<String, Object> data)throws IOException, TemplateException {Template template = configuration.getTemplate(templateName);StringWriter writer = new StringWriter();template.process(data, writer);return writer.toString();}}/*** 原生XHTML模板(直接使用)*/public static class XhtmlRenderer {public String render(String templatePath, Map<String, Object> data) throws Exception {String templateContent = loadTemplate(templatePath);// 简单替换变量(实际项目可替换为更复杂的逻辑)if (data != null) {for (Map.Entry<String, Object> entry : data.entrySet()) {String placeholder = "${" + entry.getKey() + "}";templateContent = templateContent.replace(placeholder,String.valueOf(entry.getValue()));}}return templateContent;}}/*** 加载模板文件*/private static String loadTemplate(String templatePath) throws IOException {try (InputStream is = TemplateEngine.class.getClassLoader().getResourceAsStream(templatePath)) {if (is == null) {throw new FileNotFoundException("模板文件未找到: " + templatePath);}return readInputStream(is);}}/*** 读取输入流*/private static String readInputStream(InputStream is) throws IOException {StringBuilder content = new StringBuilder();try (BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {String line;while ((line = reader.readLine()) != null) {content.append(line).append("\n");}}return content.toString();}}

4. 图片处理工具类

package com.example.pdf.util;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Base64;
/**
* 图片处理工具类(原创实现)
* 解决Flying Saucer图片嵌入问题
*/
public class ImageProcessor {
/**
* 将图片文件转换为Base64编码
* @param imageFile 图片文件
* @return Base64编码的图片字符串
*/
public static String imageToBase64(File imageFile) throws IOException {
if (!imageFile.exists()) {
throw new IllegalArgumentException("图片文件不存在: " + imageFile.getPath());
}
byte[] imageBytes = Files.readAllBytes(imageFile.toPath());
String base64 = Base64.getEncoder().encodeToString(imageBytes);
String mimeType = getMimeType(imageFile.getName());
return String.format("data:%s;base64,%s", mimeType, base64);
}
/**
* 将图片字节数组转换为Base64编码
* @param imageBytes 图片字节数组
* @param fileName 文件名(用于确定MIME类型)
* @return Base64编码的图片字符串
*/
public static String bytesToBase64(byte[] imageBytes, String fileName) {
if (imageBytes == null || imageBytes.length == 0) {
return "";
}
String base64 = Base64.getEncoder().encodeToString(imageBytes);
String mimeType = getMimeType(fileName);
return String.format("data:%s;base64,%s", mimeType, base64);
}
/**
* 根据文件名获取MIME类型
*/
private static String getMimeType(String fileName) {
if (fileName == null) {
return "image/jpeg";
}
fileName = fileName.toLowerCase();
if (fileName.endsWith(".png")) return "image/png";
if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) return "image/jpeg";
if (fileName.endsWith(".gif")) return "image/gif";
if (fileName.endsWith(".bmp")) return "image/bmp";
if (fileName.endsWith(".svg")) return "image/svg+xml";
if (fileName.endsWith(".tiff") || fileName.endsWith(".tif")) return "image/tiff";
return "image/jpeg";
}
/**
* 下载网络图片并转换为Base64
* @param imageUrl 图片URL
* @return Base64编码的图片字符串
*/
public static String downloadImageToBase64(String imageUrl) {
try {
// 使用Hutool简化HTTP请求
byte[] bytes = cn.hutool.http.HttpUtil.downloadBytes(imageUrl);
return bytesToBase64(bytes, getFileNameFromUrl(imageUrl));
} catch (Exception e) {
throw new RuntimeException("下载图片失败: " + imageUrl, e);
}
}
/**
* 从URL提取文件名
*/
private static String getFileNameFromUrl(String url) {
if (url == null || url.isEmpty()) {
return "image.jpg";
}
int lastSlash = url.lastIndexOf('/');
if (lastSlash >= 0 && lastSlash < url.length() - 1) {
return url.substring(lastSlash + 1);
}
return "image.jpg";
}
}

5. 使用示例

5.1 使用Velocity模板

模板文件:templates/velocity/report.vm

<!DOCTYPE html><html><head><meta charset="UTF-8"><title>业务报告</title><style>body { font-family: "SimSun", sans-serif; }.header { text-align: center; }.logo { width: 100px; height: 60px; }.table { border-collapse: collapse; width: 100%; }.table th, .table td { border: 1px solid #ddd; padding: 8px; }</style></head><body><div class="header"><h1>$report.title</h1><p>生成日期: $dateUtil.format($report.date, "yyyy年MM月dd日")</p></div><table class="table"><thead><tr><th>序号</th><th>项目名称</th><th>金额</th><th>备注</th></tr></thead><tbody>#foreach($item in $report.items)<tr><td>$velocityCount</td><td>$item.name</td><td>¥$number.format('#,##0.00', $item.amount)</td><td>$item.remark</td></tr>#end</tbody></table><div style="margin-top: 30px;"><p>总计: ¥$number.format('#,##0.00', $report.totalAmount)</p>#if($report.signature)<p>签章:</p><img src="$report.signature" alt="电子签章" style="width: 120px;"/>#end</div></body></html>

Java代码:

// 使用Velocity模板生成PDF
TemplateEngine.VelocityRenderer velocityRenderer =
new TemplateEngine.VelocityRenderer();
Map<String, Object> data = new HashMap<>();// 准备数据...data.put("report", reportData);// 将图片转换为Base64String signatureBase64 = ImageProcessor.imageToBase64(new File("signature.png"));data.put("report.signature", signatureBase64);// 渲染模板String html = velocityRenderer.render("templates/velocity/report.vm",data);// 生成PDFPdfGenerator.generatePdf(html,"report.pdf","fonts/simsun.ttc");
5.2 使用FreeMarker模板

模板文件:templates/freemarker/invoice.ftl

<!DOCTYPE html><html><head><meta charset="UTF-8"><title>发票</title><style>body { font-family: "SimSun", sans-serif; font-size: 12px; }.invoice-table { border-collapse: collapse; width: 100%; }.invoice-table th { background-color: #f2f2f2; }</style></head><body><h2 style="text-align: center;">增值税专用发票</h2><table class="invoice-table"><tr><td colspan="2">购方: ${buyer.name!""}</td><td colspan="2">销方: ${seller.name!""}</td></tr><#list items as item><tr><td>${item_index + 1}</td><td>${item.productName!""}</td><td>${item.quantity!0}</td><td>¥${item.price?string("#,##0.00")}</td></tr></#list></table><div style="margin-top: 20px;"><p>合计金额: ¥${totalAmount?string("#,##0.00")}</p><#if qrCode??><img src="${qrCode}" alt="二维码" style="width: 80px; height: 80px;"/></#if></div></body></html>

Java代码:

// 使用FreeMarker模板生成PDF
TemplateEngine.FreeMarkerRenderer freemarkerRenderer =
new TemplateEngine.FreeMarkerRenderer("templates/freemarker");
Map<String, Object> data = new HashMap<>();// 准备数据...// 生成二维码Base64String qrCodeBase64 = generateQrCodeBase64("发票编号: INV001");data.put("qrCode", qrCodeBase64);// 渲染模板String html = freemarkerRenderer.render("invoice.ftl", data);// 生成PDFPdfGenerator.generatePdf(html,"invoice.pdf","/usr/share/fonts/chinese/SimSun.ttf");
5.3 使用原生XHTML模板

模板文件:templates/xhtml/certificate.xhtml

<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head><meta charset="UTF-8"/><title>荣誉证书</title><style>@page {size: A4 landscape;margin: 50px;}body {font-family: "SimSun", "STSong", serif;background-image: url('${backgroundImage}');background-size: cover;text-align: center;}.certificate {padding: 100px;}.title {font-size: 36px;font-weight: bold;color: #b22222;margin-bottom: 60px;}.content {font-size: 24px;line-height: 1.8;margin-bottom: 40px;}.signature {font-size: 18px;margin-top: 80px;}.stamp {position: absolute;right: 150px;bottom: 150px;width: 120px;height: 120px;opacity: 0.9;}</style></head><body><div class="certificate"><div class="title">荣誉证书</div><div class="content">兹授予 <strong>${recipientName}</strong> 同志<br/>在${year}年度${achievement}中表现突出,<br/>特发此证,以资鼓励。</div><div class="signature"><p>${organizationName}</p><p>${issueDate}</p></div><img src="${stampImage}" class="stamp" alt="公章"/></div></body>
</html>

Java代码:

// 使用原生XHTML模板生成PDF
TemplateEngine.XhtmlRenderer xhtmlRenderer =
new TemplateEngine.XhtmlRenderer();
Map<String, Object> data = new HashMap<>();data.put("recipientName", "张三");data.put("year", "2024");data.put("achievement", "技术研发项目");// 将印章图片转换为Base64String stampBase64 = ImageProcessor.imageToBase64(new File("stamp.png"));data.put("stampImage", stampBase64);// 背景图片(使用Base64或文件路径)data.put("backgroundImage","data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAAAAAAAD/...");// 渲染模板String html = xhtmlRenderer.render("templates/xhtml/certificate.xhtml",data);// 生成PDFPdfGenerator.generatePdf(html,"certificate.pdf","classpath:fonts/simsun.ttc");

6. 高级功能:缓存和性能优化

package com.example.pdf.advanced;
import com.example.pdf.core.PdfGenerator;
import com.example.pdf.template.TemplateEngine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* 高级PDF生成服务(原创实现)
* 包含模板缓存、异步生成等功能
*/
public class AdvancedPdfService {
private static final Logger log = LoggerFactory.getLogger(AdvancedPdfService.class);
// 模板缓存
private final Map<String, String> templateCache = new ConcurrentHashMap<>();// 清理缓存的调度器private final ScheduledExecutorService scheduler =Executors.newScheduledThreadPool(1);public AdvancedPdfService() {// 每小时清理一次缓存scheduler.scheduleAtFixedRate(() -> {log.info("清理模板缓存,当前大小: {}", templateCache.size());templateCache.clear();}, 1, 1, TimeUnit.HOURS);}/*** 带缓存的模板渲染*/public String renderWithCache(String templatePath,Map<String, Object> data,String engineType) throws Exception {String cacheKey = templatePath + "|" + engineType;String templateContent = templateCache.get(cacheKey);if (templateContent == null) {templateContent = loadTemplateContent(templatePath);templateCache.put(cacheKey, templateContent);log.debug("缓存模板: {}", cacheKey);}return renderTemplate(templateContent, data, engineType);}/*** 异步生成PDF*/public void generatePdfAsync(String templatePath,Map<String, Object> data,String outputPath,String fontPath,String engineType) {Executors.newSingleThreadExecutor().submit(() -> {try {String html = renderWithCache(templatePath, data, engineType);PdfGenerator.generatePdf(html, outputPath, fontPath);log.info("异步PDF生成完成: {}", outputPath);} catch (Exception e) {log.error("异步PDF生成失败", e);}});}/*** 批量生成PDF*/public void batchGeneratePdf(String templatePath,Iterable<Map<String, Object>> dataList,String outputPattern,String fontPath,String engineType) {int index = 0;for (Map<String, Object> data : dataList) {String outputPath = String.format(outputPattern, index++);generatePdfAsync(templatePath, data, outputPath, fontPath, engineType);}}/*** 加载模板内容*/private String loadTemplateContent(String templatePath) throws Exception {try (java.io.InputStream is = getClass().getClassLoader().getResourceAsStream(templatePath)) {if (is == null) {throw new IllegalArgumentException("模板未找到: " + templatePath);}return new String(is.readAllBytes(), java.nio.charset.StandardCharsets.UTF_8);}}/*** 渲染模板*/private String renderTemplate(String templateContent,Map<String, Object> data,String engineType) throws Exception {switch (engineType.toLowerCase()) {case "velocity":return renderVelocity(templateContent, data);case "freemarker":return renderFreemarker(templateContent, data);case "xhtml":return renderXhtml(templateContent, data);default:throw new IllegalArgumentException("不支持的模板引擎: " + engineType);}}private String renderVelocity(String templateContent, Map<String, Object> data)throws Exception {// Velocity渲染实现...return templateContent; // 简化示例}private String renderFreemarker(String templateContent, Map<String, Object> data)throws Exception {// FreeMarker渲染实现...return templateContent; // 简化示例}private String renderXhtml(String templateContent, Map<String, Object> data) {// XHTML简单变量替换String result = templateContent;for (Map.Entry<String, Object> entry : data.entrySet()) {String placeholder = "${" + entry.getKey() + "}";result = result.replace(placeholder,entry.getValue() != null ? entry.getValue().toString() : "");}return result;}/*** 关闭服务*/public void shutdown() {scheduler.shutdown();try {if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) {scheduler.shutdownNow();}} catch (InterruptedException e) {scheduler.shutdownNow();Thread.currentThread().interrupt();}}}

关键问题解决方案

1. 中文字体显示问题

核心解决方案

// 关键代码:添加中文字体
renderer.getFontResolver().addFont(
"fonts/simsun.ttc",  // 字体文件路径
BaseFont.IDENTITY_H, // 使用Unicode编码
BaseFont.EMBEDDED    // 嵌入字体
);

字体文件获取

  1. Windows系统:C:/Windows/Fonts/simsun.ttc
  2. Linux系统:/usr/share/fonts/chinese/SimSun.ttf
  3. 将字体文件打包到项目resources中

2. 图片显示问题

Base64解决方案
在PDF中插入 png图片的base64格式

<!-- 在HTML模板中使用Base64图片 --><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..." />

参考GitHub Issue

  • Flying Saucer Base64 Image Support

3. 性能优化建议

  1. 模板缓存:避免重复读取和解析模板文件
  2. 字体缓存:字体只需加载一次
  3. 异步生成:批量处理时使用线程池
  4. 图片优化
    • 压缩图片减小体积
    • 使用WebP格式(需转换)
    • 懒加载非必要图片

总结

本文提供了完整的Flying Saucer PDF生成解决方案,具有以下特点:

核心优势

  1. 多模板引擎支持:Velocity、FreeMarker、原生XHTML
  2. 完美中文支持:通过嵌入字体解决乱码问题
  3. 图片兼容性好:Base64编码避免路径问题
  4. 高性能设计:支持缓存和异步生成

使用场景

  • 业务报表:销售报表、财务报表
  • 证书文档:毕业证、荣誉证书
  • 合同协议:电子合同、协议文件
  • 发票单据:增值税发票、收据

注意事项

  1. 字体文件需要合法授权
  2. Base64图片会增加HTML体积
  3. 复杂布局需要CSS支持

参考资料

本文代码为原创实现,参考了实际项目经验。相关技术参考:

  1. Flying Saucer GitHub Repository
  2. Base64 Image Support Issue
  3. Velocity Engine Documentation
  4. FreeMarker Documentation

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1174002.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

专业老酒回收公司 京城亚南高价收茅台五粮液有保障 十年口碑值得信赖 - 品牌排行榜单

在老酒回收行业,口碑是企业最好的名片。随着老酒市场的发展,越来越多的回收机构涌现,但真正具备专业资质、诚信经营的企业却寥寥无几。很多藏友因为选错了回收机构,不仅没卖到合理的价格,还遭遇了调包、欺诈等问题…

2026年温度保险丝厂家专业推荐榜:惠州市凯森电子有限公司,提供65℃/72℃/轴向/金属壳温度保险丝及电饭煲电水壶专用系列 - 品牌推荐官

温度保险丝,亦称热熔断体,是一种不可复位的一次性热敏保护器件。它虽不起眼,却是保障家用电器、电力设备乃至生命安全的关键防线。全球市场规模在2021年已达到18.6亿元,国内市场规模超过12.2亿元,凸显了其在现代工…

LLM real-time image quality check prevents misdiagnosis

&#x1f4dd; 博客主页&#xff1a;Jax的CSDN主页 实时影像质量守护者&#xff1a;LLM如何预防医疗误诊目录实时影像质量守护者&#xff1a;LLM如何预防医疗误诊 引言&#xff1a;被忽视的误诊“隐形推手” 一、影像质量&#xff1a;误诊的“沉默元凶” 问题根源&#xff1a;质…

记一次Qt视频监控平台的优化/双击打开分组可能崩溃的BUG/排对打开通道过程中关闭通道可能崩溃的BUG

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

2025年最新折弯非标钣金定制加工厂口碑推荐榜,数控非标钣金定制品牌睿意达市场认可度高 - 品牌推荐师

随着制造业向智能化、定制化方向加速转型,非标钣金定制作为工业设计落地的关键环节,其加工精度、交付效率与成本控制能力已成为企业竞争力的核心指标。然而,当前行业仍面临设备同质化严重、工艺稳定性不足、供应链响…

2026年手术器械消毒筐厂家权威推荐榜单:医疗消毒筐/消毒筐灭菌筐/冲孔消毒筐/供应室消毒筐/304不锈钢消毒筐源头厂家精选 - 品牌推荐官

在医疗行业,消毒筐作为手术器械、医用物品清洗与灭菌的关键载体,其质量直接影响医疗安全与效率。据行业统计,全国医疗机构每年对消毒筐的需求量超过500万件,其中手术室消毒筐占比达40%,医用消毒筐、供应室消毒筐等…

2026河北loft户型装修方案推荐榜:半包装修/ 奶油风局部装修/ 个性化定制装修 /装修设计/ 小户型装修 /一站式装修服务商精选 - 品牌推荐官

在涿州装修市场,选择一家专业、可靠的装修服务机构是业主实现理想家居的关键。松然装饰作为深耕涿州本地的专业化装修服务机构,凭借多年行业经验与优质服务,成为众多业主的优选合作伙伴。据统计,松然装饰累计服务涿…

整箱老酒高价收 京城亚南全国上门安全交易 茅台五粮液收藏变现不用愁 - 品牌排行榜单

对于老酒收藏爱好者来说,整箱的茅台、五粮液不仅收藏价值更高,变现时也更受青睐。但整箱老酒的回收难度也更大,很多回收渠道要么不回收整箱酒,要么给出的价格极低,还要求客户自行搬运,让不少藏友倍感困扰。京城亚…

救命神器9个一键生成论文工具,专科生毕业论文救星!

救命神器9个一键生成论文工具&#xff0c;专科生毕业论文救星&#xff01; 论文写作的“隐形助手”&#xff1a;AI 工具如何改变你的学术之路 对于专科生而言&#xff0c;撰写毕业论文不仅是学业的重要环节&#xff0c;更是对综合能力的一次全面考验。然而&#xff0c;面对繁杂…

异步线程ACPI!ACPIWorker中ACPI!RestartCtxtPassive函数对节点BAT1方法_STA的处理

异步线程ACPI!ACPIWorker中ACPI!RestartCtxtPassive函数对节点BAT1方法_STA的处理1: kd> G Breakpoint 3 hit eaxf7420746 ebx00000000 ecx899050e8 edx00000000 esi899050ec edif743b318 eipf7420746 espf791ad68 ebpf791adac iopl0 nv up ei pl zr na pe nc cs000…

2026年纸箱封箱机制造优选:哪家厂家质量更胜一筹?封箱机/角边封箱机/包装流水线,纸箱封箱机实力厂家怎么选择 - 品牌推荐师

在制造业转型升级与物流效率需求激增的双重驱动下,纸箱封箱机作为后道包装环节的关键设备,其重要性日益凸显。面对市场上品牌繁多、质量参差不齐的现状,如何甄选出性能稳定、服务可靠、性价比高的设备供应商,成为众…

警惕新型网络攻击:黑客借虚假ChatGPT指令传播MacStealer恶意软件

网络安全警报&#xff1a;MacStealer恶意软件通过虚假ChatGPT提示传播 安全研究人员发现&#xff0c;攻击者正在利用ChatGPT诱骗Mac用户将命令行粘贴到终端中&#xff0c;从而安装恶意软件。具体而言&#xff0c;其会安装MacStealer&#xff0c;该恶意软件允许攻击者获取iCloud…

2026兰州高三辅导冲刺班机构推荐榜:高考冲刺班价格 /初中冲刺班 /高考前冲刺班/ 中考数学冲刺班 /高考考前冲刺班机构精选 - 品牌推荐官

在兰州,中高考培训一直是学生和家长关注的焦点。据统计,每年有超过3万名中考生和2.5万名高考生面临升学压力,而选择一所专业、靠谱的冲刺班成为关键。兰州**学校作为兰州市城关区教育局批准成立的专业教育机构,凭借…

2026空调新材料讨论升温?美的官方定调:舆论误读技术研究,国内在售全系仍是纯铜管 - 速递信息

近期,随着大宗原材料价格波动,关于“空调是否引入新材料(铝代铜)”的讨论在舆论场持续升温,甚至衍生出针对美的等头部品牌的不实传言。 针对市场疑虑,官方最新回应已明确事实:所谓的“新材料应用”目前仅限于行…

zynqmpsoc linux如何启动自动执行.sh

修改profile文件 在/etc/profile.d/目录下创建脚本&#xff1a; sudo nano /etc/profile.d/myscript.sh#!/bin/bash /path/to/your/script.sh &自启动&#xff1a;

2026年河南手机桌面提醒便签服务推荐榜:提醒便签记事本下载/ 便签待办软件推荐 /电脑桌面日历便签/ 桌面记事本便签软件/ 好用的便签软件服务精选 - 品牌推荐官

在数字化办公与个人时间管理需求日益增长的背景下,备忘录软件已成为提升效率的重要工具。根据2025年行业调研数据显示,国内备忘录软件市场规模已突破12亿元,用户数量超过2.3亿,其中桌面端与移动端协同使用的用户占…

2026年冲洗卷盘箱厂家推荐榜:福建省首阀消防科技有限公司,冲洗卷盘/高压冲洗卷盘/矿用冲洗卷盘箱/不锈钢冲洗卷盘/矿山冲洗卷盘厂家精选 - 品牌推荐官

在消防设备领域,冲洗卷盘箱、冲洗卷盘、高压冲洗卷盘等产品的技术迭代与市场需求同步增长。据行业统计,2025年国内消防设备市场规模达420亿元,其中冲洗类设备占比约12%,年增长率稳定在8%以上。在众多生产企业中,福…

微栖智能装备好用吗,十大好用品牌排名 - 工业品牌热点

2026年文旅产业与乡村振兴战略深度融合,精智化移动空间已成为文旅营地、康养旅居、乡村公共配套的核心载体。无论是生态友好型栖居空间的研发、全地形适配的产品设计,还是从生产到运营的一站式解决方案,优质服务商的…

zynq mpsoc 以太网联网脚本

1静态IP #!/bin/bash # 使用ifconfig的版本INTERFACE="eth0" IP_ADDR="192.168.1.10" NETMASK="255.255.255.0" BROADCAST="192.168.1.255"# 检查root权限

zynq mpsoc 以太网联网脚本

1静态IP #!/bin/bash # 使用ifconfig的版本INTERFACE="eth0" IP_ADDR="192.168.1.10" NETMASK="255.255.255.0" BROADCAST="192.168.1.255"# 检查root权限