gpt4 book ai didi

java - 如何将 HTML 转换为格式良好且样式属性完好的 DOCX

转载 作者:行者123 更新时间:2023-12-01 18:23:52 30 4
gpt4 key购买 nike

我正在尝试使用 docx4j 将 HTML5 文件转换为 docx。更大的情况是 HTML 包含阿拉伯语数据和英语数据。我已经在 HTML 中的元素上设置了样式。我的 HTML 在 Chrome 上看起来很整洁,但是当我使用 docx4j 转换为 docx 时,阿拉伯文本格式会丢失。在 MS Word 上,它显示我的阿拉伯文本设置了粗体样式,但它不是粗体。同样,RTL 方向也会丢失。表从 RTL 颠倒到 LTR。作为解决方法,我使用 BufferedWriter 生成 .doc 文件,该文件将我的 HTML 文件与样式属性相匹配,但 html 中存在 Base64 图像,该图像不会出现在 .doc 文件中。因此,需要转换为 .docx 格式。我的要求是从我的 HTML 生成一个可编辑的文档。请指导我,因为我一直在摸不着头脑。没有源示例代码也可以工作。

这是我用来将 HTML 转换为 docx 的代码。

public boolean convertHTMLToDocx(String inputFilePath, String outputFilePath, boolean headerFlag,
boolean footerFlag,String orientation, String logoPath, String margin, JSONObject json,boolean isArabic) {
boolean conversionFlag;
boolean orientationFlag = false;
try {
if(!orientation.equalsIgnoreCase("Y")){
orientationFlag = true;
}
String stringFromFile = FileUtils.readFileToString(new File(inputFilePath), "UTF-8");
String unescaped = stringFromFile;
WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage();
NumberingDefinitionsPart ndp = new NumberingDefinitionsPart();
wordMLPackage.getMainDocumentPart().addTargetPart(ndp);
ndp.unmarshalDefaultNumbering();

ImportXHTMLProperties.setProperty("docx4j-ImportXHTML.Bidi.Heuristic", true);
ImportXHTMLProperties.setProperty("docx4j-ImportXHTML.Element.Heading.MapToStyle", true);
ImportXHTMLProperties.setProperty("docx4j-ImportXHTML.fonts.default.serif", "Frutiger LT Arabic 45 Light");
ImportXHTMLProperties.setProperty("docx4j-ImportXHTML.fonts.default.sans-serif", "Frutiger LT Arabic 45 Light");
ImportXHTMLProperties.setProperty("docx4j-ImportXHTML.fonts.default.monospace", "Frutiger LT Arabic 45 Light");

XHTMLImporterImpl xHTMLImporter = new XHTMLImporterImpl(wordMLPackage);
xHTMLImporter.setHyperlinkStyle("Hyperlink");
xHTMLImporter.setParagraphFormatting(FormattingOption.CLASS_PLUS_OTHER);
xHTMLImporter.setTableFormatting(FormattingOption.CLASS_PLUS_OTHER);
xHTMLImporter.setRunFormatting(FormattingOption.CLASS_PLUS_OTHER);

wordMLPackage.getMainDocumentPart().getContent().addAll(xHTMLImporter.convert(unescaped, ""));

XmlUtils.marshaltoString(wordMLPackage.getMainDocumentPart().getJaxbElement(),true,true);
File output = new File(outputFilePath);

wordMLPackage.save(output);

Console.log("file path where it is stored is" + " " + output.getAbsolutePath());
if (headerFlag || footerFlag) {
File file = new File(outputFilePath);
InputStream in = new FileInputStream(file);

wordMLPackage = WordprocessingMLPackage.load(in);
if (headerFlag) {
// set Header
}
if (footerFlag) {
// set Footer
}

wordMLPackage.save(file);
Console.log("Finished editing the word document");
}
conversionFlag = true;
} catch (InvalidFormatException e) {
Error.log("Invalid format found:-" + getStackTrace(e));
conversionFlag = false;
} catch (Exception e) {
Error.log("Error while converting:-" + getStackTrace(e));
conversionFlag = false;
}

return conversionFlag;
}

最佳答案

这是我的处理方法。这不是最好的方法,但我已经看到这在组织中得到实现。在这些方法中,他们在应用程序服务器上创建 war 文件,用于托管 HTTP 请求的静态和动态内容。

因此,我使用了一个简单的字节数组写入 .doc 文件而不是 .docx。这样,最终的 Word 文档将与 html 完全相同。我面临的唯一问题是二进制图像没有显示。只有一个框出现在图像的位置。

所以,我写了两个文件:

1st- 从 html 文件中读取我所有的二进制图像标签,并使用 Base64 解码器来解码图像。将所有解码后的图像保存在我的服务器主机的磁盘上,创建该文件的路径,并将 html 中所有此类 img 标签的 src 属性替换为磁盘上的此位置。 (新位置前面带有 http://{remote_server}:{remote_port}/{war_deployment_descriptor}/images/

第二 - 我在部署在服务器上的 war 文件中创建了一个简单的 servlet,它监听/images 上的 get 请求,并在收到带有路径名的 get 请求后,在 OutputStream 上返回图像。

瞧,图像开始出现。

免责声明 - 但是,这些图像在您的网络之外将不可见。我很幸运能够严格遵守客户的网络。要使它们在外部网络上可用,您可以请求您的 IT 团队允许在开放网络或您希望可用的网络上提供图像服务的路径。问题就会解决。

编辑 - 您可以创建一个新的 war 文件来托管这些图像,或使用生成这些图像的文件。

<小时/>

我的经历-对于英文文档,请使用 docx4j 进行 .docx 转换。对于阿拉伯语、希伯来语或其他 RTL 语言,请按上述方式进行 .doc 转换。所有此类 .doc 文档都可以轻松地从 MS Word 转换为 .docx。

列出两个文件,请根据您的需要进行更改:

文件1.java

        public static void writeHTMLDatatoDoc(String content, String inputHTMLFile,String outputDocFile,String uniqueName) throws Exception {
String baseTag = getRemoteServerURL()+"/{war_deployment_desciptor}/images?image=";
String tag = "Image_";
String ext = ".png";
String srcTag = "";
String pathOnServer = getDiskPath() + File.separator + "TemplateGeneration"
+ File.separator + "generatedTemplates" + File.separator + uniqueName + File.separator + "images" + File.separator;

int i = 0;
boolean binaryimgFlag = false;

Pattern p = Pattern.compile("<img [^>]*src=[\\\"']([^\\\"^']*)");
Matcher m = p.matcher(content);
while (m.find()) {
String src = m.group();
int startIndex = src.indexOf("src=") + 5;
int endIndex = src.length();

// srcTag will contain data as data:image/png;base64,AAABAAEAEBAAAAEAGABoAw.........
// Replace this whole later with path on local disk
srcTag = src.substring(startIndex, src.length());

if(srcTag.contains("base64")) {
binaryimgFlag = true;
}
if(binaryimgFlag) {

// Extract image mime type and image extension from srcTag containing binary image
ext = extractMimeType(srcTag);
if(ext.lastIndexOf(".") != -1 && ext.lastIndexOf(".") != 0)
ext = ext.substring(ext.lastIndexOf(".")+1);
else
ext = ".png";

// read files already created for the different documents for this unique entity.
// The location contains all image files as Image_{i}.{image_extension}
// Sort files and read max counter in image names.
// Increase value of i to generate next image as Image_{incremented_i}.{image_entension}
i = findiDynamicallyFromFilesCreatedForWI(pathOnServer);
i++; // Increase count for next image

// save whole data to replace later
String srcTagBegin = srcTag;

// Remove data:image/png;base64, from srcTag , so I get only encoded image data.
// Decode this using Base64 decoder.
srcTag = srcTag.substring(srcTag.indexOf(",") + 1, srcTag.length());
byte[] imageByteArray = decodeImage(srcTag);

// Constrcu replacement tag
String replacement = baseTag+pathOnServer+tag+i+ext;
replacement = replacement.replace("\\", "/");

// Writing image inside local directory on server
FileOutputStream imageOutFile = new FileOutputStream(pathOnServer+tag+i+ext);
imageOutFile.write(imageByteArray);
content = content.replace(srcTagBegin, replacement);
imageOutFile.close();
}
}

//Re write HTML file
writeHTMLData(content,inputHTMLFile);

// write content to doc file
writeHTMLData(content,outputDocFile);
}

public static int findiDynamicallyFromFilesCreatedForWI(String pathOnServer) {
String path = pathOnServer;
int nextFileCount = 0;
String number = "";
String[] dirListing = null;
File dir = new File(path);
dirListing = dir.list();
if(dirListing.length != 0) {
Arrays.sort(dirListing);
int length = dirListing.length;
int index = dirListing[length - 1].indexOf('.');
number = dirListing[length - 1].substring(0,index);
int index1 = number.indexOf('_');
number = number.substring(index1+1,number.length());
nextFileCount = Integer.parseInt(number);
}
return nextFileCount;
}

private static String extractMimeType(final String encoded) {
final Pattern mime = Pattern.compile("^data:([a-zA-Z0-9]+/[a-zA-Z0-9]+).*,.*");
final Matcher matcher = mime.matcher(encoded);
if (!matcher.find())
return "";
return matcher.group(1).toLowerCase();
}

private static void writeHTMLData(String inputData, String outputFilepath) {
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(outputFilepath)), Charset.forName("UTF-8")));
writer.write(inputData);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(writer != null)
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

public static byte[] decodeImage(String imageDataString) {
return Base64.decodeBase64(imageDataString);
}

private static String readHTMLData(String inputFile) {
String data = "";
String str = "";

try (BufferedReader reader = new BufferedReader(
new InputStreamReader(new FileInputStream(new File(inputFile)), StandardCharsets.UTF_8))) {
while ((str = reader.readLine()) != null) {
data += str;
}
} catch (IOException e) {
e.printStackTrace();
}
return data;
}

文件2.java

 import java.io.File;
import java.io.IOException;
import java.nio.file.Files;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.newgen.clos.logging.consoleLogger.Console;
public class ImageServlet extends HttpServlet {
public void init() throws ServletException {
public ImageServlet() {
super();
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String param = request.getParameter("image");
Console.log("Image Servlet executed");
Console.log("File Name Requested: " + param);
param.replace("\"", "");
param.replace("%20"," ");
File file = new File(param);
response.setHeader("Content-Type", getServletContext().getMimeType(param));
response.setHeader("Content-Length", String.valueOf(file.length()));
response.setHeader("Content-Disposition", "inline; filename=\"" + param + "\"");
Files.copy(file.toPath(), response.getOutputStream());
}
}

关于java - 如何将 HTML 转换为格式良好且样式属性完好的 DOCX,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60262649/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com