使用Apache POI和Jsoup将Word文档转换为HTML
简介
在现代办公环境中,Word文档和HTML页面都是常见的信息表达方式。有时,我们需要将Word文档转换为HTML格式,以便在网页上展示或进行进一步的处理。本文将介绍如何使用Apache POI库和Jsoup库来实现Word文档到HTML的转换,并处理文档中的图片资源。
环境准备
Java开发环境
Apache POI库
Jsoup库
Hutool工具库(用于简化文件和字符串操作)
1. 步骤1:创建项目和依赖
- 首先,我们需要创建一个Java项目,并添加Apache POI和Jsoup库的依赖。可以通过Maven或Gradle来管理这些依赖。
<poi.version>4.1.2</poi.version>
<!--注意版本保持一致 poi poi-ooxml poi-scratchpad-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
</dependency>
<!-- 操作doc ppt xls -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>${poi.version}</version>
</dependency>
<!-- 操作docx pptx xlsx -->
<!--word S-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>ooxml-schemas</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>fr.opensagres.poi.xwpf.converter.xhtml</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>fr.opensagres.xdocreport.converter.docx.xwpf</artifactId>
<version>2.0.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.17.2</version>
</dependency>
步骤2:读取Word文档
使用Apache POI库读取Word文档。对于.docx文件,使用XWPFDocument类;对于.doc文件,使用HWPFDocument类。
docx:
/**
* 解析docx成html
*
* @param file
* @return
* @throws IOException
*/
public static String Word2007ToHtml(MultipartFile file) throws IOException {
if (file.isEmpty() || file.getSize() <= 0) {
log.error("Sorry File does not Exists!");
return null;
} else {
if (file.getOriginalFilename().endsWith(".docx") || file.getOriginalFilename().endsWith(".DOCX")) {
// 1) 加载word文档生成 XWPFDocument对象
InputStream in = file.getInputStream();
XWPFDocument document = new XWPFDocument(in);
setParagraphs(document);
//解析XHTML配置
XHTMLOptions xhtmlOptions = XHTMLOptions.create();
// 将样式都写为内联样式,而不是写到style标签中 默认false
xhtmlOptions.setFragment(true);
xhtmlOptions.setIgnoreStylesIfUnused(false);
// 也可以使用字符数组流获取解析的内容
ByteArrayOutputStream baos = new ByteArrayOutputStream();
XHTMLConverter.getInstance().convert(document, baos, xhtmlOptions);
String content = baos.toString();
org.jsoup.nodes.Document doc = setDocXStyle(content);
baos.close();
return doc.html();
} else {
log.error("Enter only MS Office 2007+ files");
return null;
}
}
}
doc读取代码
/**
* 解析doc成html 并保存图片文件到本地
*
* @param file
* @return
* @throws IOException
* @throws ParserConfigurationException
* @throws TransformerException
*/
public static String Word2003ToHtmlAndSaveImage(MultipartFile file) throws IOException {
//使用字符数组流获取解析的内容
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream outStream = new BufferedOutputStream(baos);
try {
//将上传的文件传入Document转换
HWPFDocument wordDocument = new HWPFDocument(file.getInputStream());
//处理标题
Range range = wordDocument.getRange();
HashSet<String> hashSet = new HashSet<>();
for (int i = 0; i < range.numParagraphs(); i++) {
Paragraph paragraph = range.getParagraph(i);
int lvl = paragraph.getLvl();
if (StrUtil.isNotEmpty(paragraph.text().trim())) {
//标题
if (lvl == 1 || lvl == 0 || lvl == 2 || lvl == 4) {
String newContent = HEADLINE_DJ_ + RandomUtil.randomNumbers(8) + "_";
paragraph.insertBefore(newContent);
// paragraph.replaceText(paragraph.text(), newContent+paragraph.text() );
hashSet.add(newContent);
}
}
}
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(document);
//将读取到的图片上传并添加链接地址
wordToHtmlConverter.setPicturesManager(new PicturesManager() {
@Override
public String savePicture(byte[] content, PictureType pictureType, String suggestedName, float widthInches, float heightInches) {
return getImgUrl(suggestedName, content);
}
});
// word文档转Html文档
wordToHtmlConverter.processDocument(wordDocument);
Document htmlDocument = wordToHtmlConverter.getDocument();
DOMSource domSource = new DOMSource(htmlDocument);
StreamResult streamResult = new StreamResult(outStream);
TransformerFactory factory = TransformerFactory.newInstance();
Transformer serializer = factory.newTransformer();
serializer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
serializer.setOutputProperty(OutputKeys.INDENT, "yes");
serializer.setOutputProperty(OutputKeys.METHOD, "html");
serializer.transform(domSource, streamResult);
String content = baos.toString();
// 使用Jsoup解析HTML内容
org.jsoup.nodes.Document doc = Jsoup.parse(content);
// 查找并修改目标段落
hashSet.forEach(text -> {
text = getReplaceAllNR(text);
Elements elements = doc.select("p");
String finalText = text;
elements.forEach(el -> {
if (el.text().contains(finalText)) {
Element h2Element = new Element("h2");
h2Element.text(el.text().replaceAll(finalText, ""));
h2Element.attr("style", "font-weight: bold;font-size: 22px;");
el.replaceWith(h2Element);
}
});
// 添加CSS样式
org.jsoup.select.Elements elementsfontSize = doc.select("span");
elementsfontSize.forEach(fs -> fs.attr("style", "font-size: 19px; "));
});
// log.info("docToHtmlText--->{}", content);
return doc.html();
} catch (Exception e) {
log.error("docToHtmlText 异常", e);
throw new MyException("docToHtmlText 异常!", e.getMessage());
} finally {
baos.close();
outStream.close();
}
}
步骤3:转换文档内容为HTML
对于.docx文件,使用XWPF库提供的XHTMLConverter类将文档内容转换为HTML。对于.doc文件,使用WordToHtmlConverter类进行转换。
步骤4:处理文档中的图片
在转换过程中,需要特别处理文档中的图片。对于.docx文件,可以通过遍历段落和运行(XWPFRun)来获取图片数据,并使用MinioUtil(或其他存储服务)保存图片并获取图片的URL。对于.doc文件,可以通过PicturesManager接口来处理图片的保存和链接更新。
步骤5:样式调整和优化
使用Jsoup库对生成的HTML内容进行样式调整和优化。例如,可以通过CSS选择器来定位并修改特定的元素样式。
处理html,添加h2标签到富文本,显示目录用。
// 遍历文档中的段落,标记标题
private static void setParagraphs(XWPFDocument document) {
// 遍历文档中的段落,标记标题
List<XWPFParagraph> paragraphs = document.getParagraphs();
for (XWPFParagraph paragraph : paragraphs) {
boolean isTitle = false;
String style = paragraph.getStyle();
if (StrUtil.isEmpty(style)) {
continue;
}
//paragraph.getStyle() 是获取段落标题等级
if (style.equals("1") || style.equals("2") || style.equals("3") || style.equals("4")) {
Long res = new Date().getTime();
String headline = HEADLINE_DJ_ + RandomUtil.randomNumbers(5) + "_" + res;
paragraph.setStyle(headline);
isTitle = true;
}
for (XWPFRun run : paragraph.getRuns()) {
run.setFontSize(40);
if (isTitle) {
run.setFontSize(60);
run.setBold(true);
}
}
}
}
步骤6:完整代码示例
点击查看代码
package com.csot.kms.common.poi;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.csot.kms.common.utill.MinioUtil;
import com.csot.kms.common.valid.MyException;
import fr.opensagres.poi.xwpf.converter.xhtml.XHTMLConverter;
import fr.opensagres.poi.xwpf.converter.xhtml.XHTMLOptions;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.converter.PicturesManager;
import org.apache.poi.hwpf.converter.WordToHtmlConverter;
import org.apache.poi.hwpf.usermodel.Paragraph;
import org.apache.poi.hwpf.usermodel.PictureType;
import org.apache.poi.hwpf.usermodel.Range;
import org.apache.poi.xwpf.usermodel.*;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.web.multipart.MultipartFile;
import org.w3c.dom.Document;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;
import java.util.*;
@Slf4j
public class WordToHtmlPoiUtil {
public static final String HEADLINE_DJ_ = "HEADLINE_DJ_";
public static String docImport(MultipartFile file) throws Exception {
//返回的html字符串
String html = "";
//word类型是否doc
boolean wordType = false;
//临时图片存放文件夹 图片会保存在此路径(临时保存)(doc类型使用)
String docsTempImages = System.getProperty("java.io.tmpdir") + IdUtil.simpleUUID() + "/";
//判断类型
String suffixName = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
if (file.getOriginalFilename().endsWith(".docx") || file.getOriginalFilename().endsWith(".DOCX")) {
html = WordToHtmlPoiUtil.Word2007ToHtml(file);
} else if (file.getOriginalFilename().endsWith(".doc") || file.getOriginalFilename().endsWith(".DOC")) {
wordType = true;
html = WordToHtmlPoiUtil.Word2003ToHtmlAndSaveImage(file);
}
//获取图片名称和本地url,这一步上传图片到本地,并把名字和url处理成map
// String uploadPath = "";//word中的图片上传到哪
Map<String, String> imageMaps = WordToHtmlPoiUtil.getImageMaps(docsTempImages, file);
//如果有图片替换成本地地址
if (!imageMaps.isEmpty()) {
html = replaceImgToLocal(html, imageMaps, wordType);
}
html = getReplaceAllNR(html);
return html;
}
/**
* 解析docx成html
*
* @param file
* @return
* @throws IOException
*/
public static String Word2007ToHtml(MultipartFile file) throws IOException {
if (file.isEmpty() || file.getSize() <= 0) {
log.error("Sorry File does not Exists!");
return null;
} else {
if (file.getOriginalFilename().endsWith(".docx") || file.getOriginalFilename().endsWith(".DOCX")) {
// 1) 加载word文档生成 XWPFDocument对象
InputStream in = file.getInputStream();
XWPFDocument document = new XWPFDocument(in);
setParagraphs(document);
//解析XHTML配置
XHTMLOptions xhtmlOptions = XHTMLOptions.create();
// 将样式都写为内联样式,而不是写到style标签中 默认false
xhtmlOptions.setFragment(true);
xhtmlOptions.setIgnoreStylesIfUnused(false);
// 也可以使用字符数组流获取解析的内容
ByteArrayOutputStream baos = new ByteArrayOutputStream();
XHTMLConverter.getInstance().convert(document, baos, xhtmlOptions);
String content = baos.toString();
org.jsoup.nodes.Document doc = setDocXStyle(content);
baos.close();
return doc.html();
} else {
log.error("Enter only MS Office 2007+ files");
return null;
}
}
}
private static org.jsoup.nodes.Document setDocXStyle(String content) {
//根据标记替换标题内容
org.jsoup.nodes.Document doc = Jsoup.parse(content);
Elements elements = doc.select("p[class^=HEADLINE_DJ_]");
for (Element element : elements) {
Element h2Element = new Element("h2");
h2Element.attr("style", "font-weight: bold;font-size: 22px;");
h2Element.text(element.text());
element.replaceWith(h2Element);
}
// 添加CSS样式
Elements elementsfontSize = doc.select("span");
elementsfontSize.forEach(fs -> fs.attr("style", "font-size: 19px; "));
return doc;
}
// 遍历文档中的段落,标记标题
private static void setParagraphs(XWPFDocument document) {
// 遍历文档中的段落,标记标题
List<XWPFParagraph> paragraphs = document.getParagraphs();
for (XWPFParagraph paragraph : paragraphs) {
boolean isTitle = false;
String style = paragraph.getStyle();
if (StrUtil.isEmpty(style)) {
continue;
}
if (style.equals("1") || style.equals("2") || style.equals("3") || style.equals("4")) {
Long res = new Date().getTime();
String headline = HEADLINE_DJ_ + RandomUtil.randomNumbers(5) + "_" + res;
paragraph.setStyle(headline);
isTitle = true;
}
for (XWPFRun run : paragraph.getRuns()) {
run.setFontSize(40);
if (isTitle) {
run.setFontSize(60);
run.setBold(true);
}
}
}
}
/**
* 解析doc成html 并保存图片文件到本地
*
* @param file
* @return
* @throws IOException
* @throws ParserConfigurationException
* @throws TransformerException
*/
public static String Word2003ToHtmlAndSaveImage(MultipartFile file) throws IOException {
//使用字符数组流获取解析的内容
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream outStream = new BufferedOutputStream(baos);
try {
//将上传的文件传入Document转换
HWPFDocument wordDocument = new HWPFDocument(file.getInputStream());
//处理标题
Range range = wordDocument.getRange();
HashSet<String> hashSet = new HashSet<>();
for (int i = 0; i < range.numParagraphs(); i++) {
Paragraph paragraph = range.getParagraph(i);
int lvl = paragraph.getLvl();
if (StrUtil.isNotEmpty(paragraph.text().trim())) {
//标题
if (lvl == 1 || lvl == 0 || lvl == 2 || lvl == 4) {
String newContent = HEADLINE_DJ_ + RandomUtil.randomNumbers(8) + "_";
paragraph.insertBefore(newContent);
// paragraph.replaceText(paragraph.text(), newContent+paragraph.text() );
hashSet.add(newContent);
}
}
}
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(document);
//将读取到的图片上传并添加链接地址
wordToHtmlConverter.setPicturesManager(new PicturesManager() {
@Override
public String savePicture(byte[] content, PictureType pictureType, String suggestedName, float widthInches, float heightInches) {
return getImgUrl(suggestedName, content);
}
});
// word文档转Html文档
wordToHtmlConverter.processDocument(wordDocument);
Document htmlDocument = wordToHtmlConverter.getDocument();
DOMSource domSource = new DOMSource(htmlDocument);
StreamResult streamResult = new StreamResult(outStream);
TransformerFactory factory = TransformerFactory.newInstance();
Transformer serializer = factory.newTransformer();
serializer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
serializer.setOutputProperty(OutputKeys.INDENT, "yes");
serializer.setOutputProperty(OutputKeys.METHOD, "html");
serializer.transform(domSource, streamResult);
String content = baos.toString();
// 使用Jsoup解析HTML内容
org.jsoup.nodes.Document doc = Jsoup.parse(content);
// 查找并修改目标段落
hashSet.forEach(text -> {
text = getReplaceAllNR(text);
Elements elements = doc.select("p");
String finalText = text;
elements.forEach(el -> {
if (el.text().contains(finalText)) {
Element h2Element = new Element("h2");
h2Element.text(el.text().replaceAll(finalText, ""));
h2Element.attr("style", "font-weight: bold;font-size: 22px;");
el.replaceWith(h2Element);
}
});
// 添加CSS样式
org.jsoup.select.Elements elementsfontSize = doc.select("span");
elementsfontSize.forEach(fs -> fs.attr("style", "font-size: 19px; "));
});
// log.info("docToHtmlText--->{}", content);
return doc.html();
} catch (Exception e) {
log.error("docToHtmlText 异常", e);
throw new MyException("docToHtmlText 异常!", e.getMessage());
} finally {
baos.close();
outStream.close();
}
}
private static String getReplaceAllNR(String text) {
text = text.replaceAll("\r\n", "")
.replaceAll("\r", "")
.replaceAll("\n", "");
return text;
}
/**
* 获取word中的图片名称和本地url(doc或docx)
* 返回map<图片名称, 存储的图片url地址>
*
* @param
* @param docsTempImages 本地临时图片存放地址(这个工具类Word2003ToHtmlAndSaveImage的方法存到了系统临时文件夹里)
* @param file
* @return
* @throws IOException
*/
public static Map<String, String> getImageMaps(String docsTempImages, MultipartFile file) throws Exception {
//返回map
HashMap<String, String> map = new HashMap<>();
if (file.getOriginalFilename().endsWith(".docx") || file.getOriginalFilename().endsWith(".DOCX")) {
//获取存在word里的图片文件
InputStream in = file.getInputStream();
XWPFDocument document = new XWPFDocument(in);
List<XWPFParagraph> paragraphs = document.getParagraphs();
if (CollUtil.isNotEmpty(paragraphs)) {
paragraphs.forEach(p -> {
List<XWPFRun> runs = p.getRuns();
if (CollUtil.isNotEmpty(runs)) {
runs.forEach(r -> {
List<XWPFPicture> pictures = r.getEmbeddedPictures();
if (CollUtil.isNotEmpty(pictures)) {
pictures.forEach(c -> {
//这里找到word中的图片的名字和数据
XWPFPictureData pictureData = c.getPictureData();
String fileName = pictureData.getFileName();
byte[] data = pictureData.getData();
String localUrl = getImgUrl(fileName, data);
map.put(pictureData.getFileName(), localUrl);
});
}
});
}
});
}
} else if (file.getOriginalFilename().endsWith(".doc") || file.getOriginalFilename().endsWith(".DOC")) {
try {
File dir = new File(docsTempImages);
//如果目录不为空遍历存储到项目中
if (!FileUtil.isEmpty(dir)) {
Arrays.asList(FileUtil.ls(docsTempImages)).forEach(f -> {
String name = f.getName();
BufferedInputStream inputStream = FileUtil.getInputStream(f);
String localUrl = getOssImgUrl(name, inputStream);
map.put(name, localUrl);
});
}
} finally {
//删除临时文件夹
FileUtil.del(docsTempImages);
}
}
return map;
}
private static String getOssImgUrl(String name, BufferedInputStream inputStream) {
Long res = new Date().getTime();
//设置文件存储路径,可以存放在你想要指定的路径里面
// 新文件名
String newFileName = res + name.substring(name.lastIndexOf("."));
String localUrl = null;
try {
localUrl = MinioUtil.upload(inputStream, newFileName);
} catch (Exception e) {
e.printStackTrace();
}
return localUrl;
}
private static String getImgUrl(String fileName, byte[] data) {
if (data.length == 0) {
return "";
}
//保存到本地获取url
Long res = new Date().getTime();
//设置文件存储路径,可以存放在你想要指定的路径里面
// 新文件名
String newFileName = res + fileName.substring(fileName.lastIndexOf("."));
InputStream inputStream = new ByteArrayInputStream(data);
String localUrl = null;
try {
localUrl = MinioUtil.upload(inputStream, newFileName);
} catch (Exception e) {
e.printStackTrace();
}
return localUrl;
}
/**
* 替换html图片的路径
*
* @param html
* @param imageMaps
* @throws
*/
public static String replaceImgToLocal(String html, Map<String, String> imageMaps, boolean wordType) {
String returnHtml = "";
//获取当前服务器ip和端口用于图片路径
org.jsoup.nodes.Document doc = Jsoup.parse(html);
// 获取 带有src属性的img元素
Elements imgTags = doc.select("img[src]");
//替换图片
for (org.jsoup.nodes.Element element : imgTags) {
String imageName = StrUtil.subAfter(element.attr("src"), "/", true);
//根据名字获取map中的url,并覆盖之前存的word中的路径
element.attr("src", imageMaps.get(imageName));
}
returnHtml = doc.toString();
//doc格式样式在外部,所以要把style从外部移到内部
if (wordType) {
returnHtml = JsoupUtils.changeHtmlCssLineStyle(doc.toString());
}
return returnHtml;
}
}
使用Apache POI和Jsoup将Word文档转换为HTML的更多相关文章
- Java中用Apache POI生成excel和word文档
概述: 近期在做项目的过程中遇到了excel的数据导出和word的图文表报告的导出功能.最后决定用Apache POI来完毕该项功能.本文就项目实现过程中的一些思路与代码与大家共享.同一时候.也作为自 ...
- 使用poi根据模版生成word文档,支持插入数据和图片
一.制作word模版,${xxxx}是一会要替换的内容,最下面的表格是要插入数据,根据是否以$开头来判断是需要替换还是插入数据, 注意如果是需要插入数据,制作的表格模版需要一行空行,也只能有一行空行, ...
- poi根据模板导出word文档
POI结构与常用类 Apache POI是Apache软件基金会的开源项目,POI提供API给Java程序对Microsoft Office格式档案读和写的功能. .NET的开发人员则可以利用NPOI ...
- 利用POI操作不同版本号word文档中的图片以及创建word文档
我们都知道要想利用java对office操作最经常使用的技术就应该是POI了,在这里本人就不多说到底POI是什么和怎么用了. 先说本人遇到的问题,不同于利用POI去向word文档以及excel文档去写 ...
- 使用Java POI来选择提取Word文档中的表格信息
通过使用Java POI来提取Word(1992)文档中的表格信息,其中POI支持不同的ms文档类型,在具体操作中需要注意.本文主要是通过POI来提取微软2003文档中的表格信息,具体code如下(事 ...
- 使用Aspose.Words将Word文档转换为Tiff格式图片文件
用Aspose组件的优点是操作Word文档不需要安装Office就可以实现. 首先需要引用Aspose.Words.dll,链接地址:链接:https://pan.baidu.com/s/1rJvjp ...
- Java 使用 jacob 将 word 文档转换为 pdf 文件
网上查询了许许多多的博客,说利用 poi.iText.Jsoup.jdoctopdf.使用 jodconverter 来调用 openOffice 的服务来转换等等,我尝试了很多种,但要么显示不完全, ...
- 使用VBA将批量的WORD文档转换为PDF
Sub BatchConvertToPDF() Dim destFolderPath As String destFolderPath = GetFolderPath If destFolderPat ...
- DEV word文档转换为pdf文件
引用aspose.net控件2.0. docement doc=new document(文件路径和名称); doc.save(输出路径\file.pdf);
- Java将数据写入word文档(.doc)
Java可用org.apache.poi包来操作word文档.org.apache.poi包可于官网上下载,解压后各jar作用如下图所示: 可根据需求导入对应的jar. 一.HWPFDocument类 ...
随机推荐
- 新零售SaaS架构:订单履约系统的概念模型设计
订单履约系统的概念模型 订单:客户提交购物请求后,生成的买卖合同,通常包含客户信息.下单日期.所购买的商品或服务明细.价格.数量.收货地址以及支付方式等详细信息. 子订单:为了更高效地进行履约,大订单 ...
- Linux操作系统不同文件类型区别?
蓝色代表目录,绿色代表可执行文件,红色代表压缩文件.浅蓝色表示连接文件.白色表示其他文件 相关目录及作用: Bin : 存放普通用户可执行的指令 Boot: 开机引导目录 Dev:设备目录 Etc: ...
- [学习笔记]Rocket.Chat业务数据备份
Rocket.Chat 的业务数据主要存储于mongodb数据库的rocketchat库中,聊天中通过发送文件功能产生的文件储存于/app/uploads中(文件方式设置为"FileSyst ...
- MDC实现微服务链路追踪
一.问题背景 在微服务架构中,我们没办法快速定位用户在一次请求中对应的所有日志,在排查生产问题的时候会非常困难,那是因为我们在输出的日志的时候没把请求的唯一标示输出到我们的日志中,导致我们没办法根据一 ...
- centos 目录磁盘使用情况
最简单的查看方法可以使用ls -ll.ls-lh命令进行查看,当使用ls -ll,会显示成字节大小,而ls- lh会以KB.MB等为单位进行显示,这样比较直观一些. 通过命令du -h –max- ...
- Obsidian 0.15.9 知识笔记 使用说明
我感觉这个软件是一个非常好用的软件,经过初步体验. 全局搜索快捷键 Ctrl + Shift + F 打开快速切换快捷键 Ctrl + O 添加标签 #测试标签 反向链接 Obsidian支持反向链接 ...
- idea branch 分支比较 | git 查看分支命令 `git branch -vv`
git 查看分支命令 git branch -vv
- SpringBoot 学习记录 2021.05.13 Started
环境搭建 Spring Boot 2.x Java JDK 需要安装 JDK java8 也就是 1.8, 用 jdk-8u271-windows-x64.exe 网上有很多安装java8的教程,很简 ...
- Node.js解压版的环境配置及相关常用命令
下载 进入node.js官网的下载页面node.js下载页面,选择合适的版本进行下载 配置 1.设置环境变量 随便找一个地方,将文件解压出来 复制当前的路径,我的电脑右键,打开属性,左边有个高级系统配 ...
- 04_QT_Windows开发环境搭建
FFmpeg 为什么选择FFmpeg? 每个主流平台基本都有自己的音视频开发库(API),用以处理音视频数据,比如: iOS:AVFoundation.AudioUnit等 Android:Media ...