Hướng dẫn GroupDocs Viewer Java: Chuyển đổi Word sang HTML và Hiển thị tài liệu với bình luận

Giới thiệu

Nếu bạn cần convert Word to HTML trong khi giữ lại mọi ghi chú, bình luận hoặc chú thích của người đánh giá, bạn đã đến đúng nơi. Nhiều nhà phát triển Java gặp khó khăn khi việc chuyển đổi tài liệu loại bỏ phản hồi quý giá được nhúng trong tệp gốc. Hướng dẫn này sẽ chỉ cho bạn cách sử dụng GroupDocs Viewer cho Java để convert Word to HTML và hiển thị nhiều loại tài liệu — Word, Excel, PowerPoint, PDF và hơn thế nữa — mà không mất dữ liệu bình luận.

Bạn sẽ khám phá tại sao GroupDocs Viewer là lựa chọn sẵn sàng cho sản xuất, cách thiết lập môi trường, mã chính xác bạn cần, và các mẹo đã được chứng minh để giữ hiệu năng nhanh chóng ngay cả với các tệp lớn.

Hiển thị tài liệu với bình luận bằng GroupDocs.Viewer cho Java

Hiển thị tài liệu với bình luận bằng GroupDocs.Viewer cho Java

Những gì bạn sẽ thành thạo trong hướng dẫn này:

  • Cài đặt và cấu hình đầy đủ GroupDocs Viewer
  • convert Word to HTML từng bước với bình luận được bảo lưu
  • Các giải pháp khắc phục sự cố phổ biến và những lưu ý cần tránh
  • Các mẫu triển khai thực tế và các thực tiễn tốt nhất
  • Kỹ thuật tối ưu hoá hiệu năng cho môi trường sản xuất

Câu trả lời nhanh

  • GroupDocs Viewer có thể chuyển đổi Word sang HTML không? Có — bật chế độ hiển thị HTML và hỗ trợ bình luận trong một dòng mã.
  • Bình luận có được giữ lại trong đầu ra HTML không? Chắc chắn — setRenderComments(true) bảo lưu mọi bình luận và chú thích.
  • Phiên bản Java nào được yêu cầu? JDK 8 hoặc cao hơn.
  • Cần giấy phép cho môi trường sản xuất không? Giấy phép đầy đủ loại bỏ watermark và mở khóa tất cả tính năng.
  • Làm sao cải thiện tốc độ hiển thị? Hiển thị các trang cụ thể, sử dụng tài nguyên bên ngoài, và tăng kích thước heap JVM.

“convert word to html” với bình luận là gì?

“Convert Word to HTML” có nghĩa là chuyển đổi tệp Microsoft Word .docx thành tài liệu HTML sẵn sàng cho web trong khi giữ nguyên bố cục, kiểu dáng và mọi bình luận được nhúng. Quá trình này cho phép trình duyệt hiển thị tài liệu chính xác như tác giả mong muốn, kèm theo phản hồi của người đánh giá.

Tại sao chọn GroupDocs Viewer cho Java?

Trước khi chúng ta bắt đầu viết mã, hãy khám phá lý do tại sao GroupDocs Viewer là thư viện hàng đầu cho việc hiển thị tài liệu dựa trên Java:

  • Hơn 170 định dạng được hỗ trợ – thư viện xử lý mọi thứ từ DOCX đến các tệp CAD, cung cấp một phụ thuộc duy nhất cho mọi nhu cầu chuyển đổi.
  • Không cần cài đặt Office của bên thứ ba – hoạt động trên bất kỳ hệ điều hành nào mà không cần Microsoft Office, LibreOffice hoặc các runtime nặng khác.
  • Bảo lưu định dạng và chú thích – bình luận, chú thích chân trang và track changes được giữ nguyên sau khi chuyển đổi.
  • Động cơ nhanh, nhẹ – tài liệu 100 trang thường được hiển thị trong dưới 2 giây trên máy chủ tiêu chuẩn 4 nhân.
  • Tài liệu chi tiết và cộng đồng năng động – bạn sẽ tìm thấy ví dụ, diễn đàn và hỗ trợ nhanh chóng mỗi khi gặp khó khăn.

Khi nào nên sử dụng cách tiếp cận này

  • Xây dựng trình xem tài liệu trên web cần hiển thị ghi chú của người đánh giá
  • Tạo nền tảng đánh giá cộng tác nơi phản hồi phải luôn hiển thị
  • Chuyển đổi hợp đồng cũ để hiển thị trực tuyến trong các cổng pháp lý
  • Phát triển giải pháp e‑learning nhúng bình luận của giảng viên vào tài liệu học

Tiền đề và Cài đặt môi trường

Bạn sẽ cần gì

  • Java Development Kit (JDK) 8+ – môi trường chạy ứng dụng của bạn.
  • Maven 3.6+ – quản lý phụ thuộc và xây dựng dự án.
  • IDE mà bạn chọn – IntelliJ IDEA, Eclipse hoặc VS Code.
  • Tài liệu mẫu có bình luận – các tệp DOCX, XLSX, PPTX chứa ghi chú của người đánh giá.

Cài đặt môi trường phát triển của bạn

Bước 1: Xác minh cài đặt Java

Mở terminal và chạy:

java -version

Bạn sẽ thấy chuỗi phiên bản bắt đầu bằng 1.8 hoặc cao hơn. Nếu không, tải JDK mới nhất từ trang web chính thức của Oracle hoặc OpenJDK.

Bước 2: Kiểm tra cài đặt Maven

Chạy:

mvn -v

Maven sẽ báo cáo phiên bản và phiên bản Java đang sử dụng. Cài đặt Maven từ trang Apache nếu lệnh không được nhận dạng.

Bước 3: Tạo dự án Maven mới

Tạo dự án khung với:

mvn archetype:generate -DgroupId=com.example.viewer -DartifactId=viewer-demo -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

Di chuyển vào thư mục viewer-demo vừa tạo và bạn đã sẵn sàng thêm GroupDocs Viewer.

Cài đặt GroupDocs.Viewer cho Java

Thêm phụ thuộc

Bước đầu tiên trong bất kỳ hướng dẫn GroupDocs Viewer Java nào là đưa thư viện vào dự án. Thêm cấu hình này vào tệp pom.xml của bạn:

<dependency>
    <groupId>com.groupdocs</groupId>
    <artifactId>groupdocs-viewer</artifactId>
    <version>25.2</version>
</dependency>

Mẹo chuyên nghiệp: Luôn kiểm tra trang phát hành GroupDocs để có phiên bản mới nhất. Thư viện được duy trì tích cực với các bản cập nhật và sửa lỗi thường xuyên.

Hiểu các tùy chọn cấp phép

GroupDocs cung cấp các gói cấp phép linh hoạt phù hợp với nhu cầu dự án khác nhau:

  • Dùng thử miễn phí (Lý tưởng cho học tập): Đánh giá 30 ngày với đầy đủ tính năng và watermark đánh giá.
  • Giấy phép tạm thời (Dành cho phát triển): Đánh giá kéo dài không có watermark; lý tưởng cho các dự án proof‑of‑concept. Yêu cầu tại trang Giấy phép Tạm thời của GroupDocs.
  • Giấy phép đầy đủ (Sẵn sàng cho sản xuất): Không giới hạn hoặc watermark, cho phép sử dụng thương mại. Có sẵn tại trang Mua GroupDocs.

Mẫu khởi tạo cơ bản

Đây là mẫu cơ bản bạn sẽ dùng xuyên suốt hướng dẫn:

try (Viewer viewer = new Viewer("input.docx")) {
    // Rendering options will be set later
}

Tại sao mẫu này hoạt động:

  • Quản lý tài nguyên tự động ngăn rò rỉ bộ nhớ.
  • Xử lý ngoại lệ bắt các vấn đề thường gặp khi truy cập tệp.
  • Mã sạch, dễ đọc giúp bảo trì dễ dàng trong các dự án lớn.

Triển khai cốt lõi: Hiển thị tài liệu với bình luận

Hiểu quy trình

Khi bạn hiển thị tài liệu bằng GroupDocs Viewer, thư viện thực hiện bốn bước chính:

  1. Document Analysis – phân tích tệp đầu vào và xây dựng biểu diễn nội bộ.
  2. Comment Extraction – xác định mọi bình luận, chú thích chân trang và annotation.
  3. HTML Generation – tạo HTML sạch, tuân chuẩn, phản ánh đúng bố cục gốc.
  4. Resource Handling – gói hình ảnh, CSS và font dưới dạng nội tuyến hoặc tệp bên ngoài.

Triển khai từng bước

Bước 1: Thiết lập đường dẫn tệp

Sắp xếp vị trí nhập và xuất ngay từ đầu để tránh lỗi liên quan đến đường dẫn:

Path inputPath = Paths.get("documents/sample-with-comments.docx");
Path outputDir = Paths.get("output/html");
Files.createDirectories(outputDir);

Lý do chọn cách này:

  • Sử dụng API Path hiện đại của Java NIO.2, đáng tin cậy hơn java.io.File.
  • Tên biến mô tả giúp việc gỡ lỗi dễ dàng hơn.
  • {0} trong mẫu đầu ra sẽ tự động được thay thế bằng số trang.

Bước 2: Cấu hình tùy chọn hiển thị HTML

Đây là nơi phép thuật xảy ra. Chúng ta chỉ định cho GroupDocs cách hiển thị tài liệu:

HtmlViewOptions cấu hình cách tài liệu được chuyển sang HTML, bao gồm xử lý tài nguyên và hiển thị bình luận.

HtmlViewOptions viewOptions = HtmlViewOptions.forEmbeddedResources(outputDir);
viewOptions.setRenderComments(true);   // Preserve every comment
viewOptions.setPageNumberPrefix("page_");

Chi tiết cấu hình chính:

  • forEmbeddedResources() nhúng CSS, hình ảnh và font trực tiếp vào HTML, làm cho đầu ra di động.
  • setRenderComments(true) là dòng lệnh duy nhất đảm bảo convert word to html giữ lại mọi ghi chú của người đánh giá.
  • forExternalResources() cho phép lưu tài nguyên riêng nếu bạn muốn tệp HTML nhẹ hơn.

Bước 3: Thực thi quá trình hiển thị

Bây giờ chúng ta kết hợp mọi thứ lại:

Viewer là lớp chính dùng để tải tài liệu và thực hiện các thao tác hiển thị.

try (Viewer viewer = new Viewer(inputPath.toFile())) {
    viewer.view(viewOptions);
}

Lệnh view đọc tệp Word, trích xuất bình luận, tạo các trang HTML và ghi chúng vào output/html. Mỗi trang được lưu dưới dạng page_1.html, page_2.html, v.v.

Ví dụ làm việc đầy đủ

Kết hợp tất cả các phần lại sẽ cho bạn một lớp chạy được, chuyển đổi tài liệu Word sang HTML trong khi giữ bình luận nguyên vẹn. (Mã nguồn đầy đủ có trên kho GitHub chính thức.)

Cấu hình nâng cao và các tùy chọn

Thiết lập thư mục đầu ra động

Đối với các ứng dụng lớn, bạn có thể muốn tạo thư mục đầu ra dựa trên ID người dùng hoặc dấu thời gian:

String userId = "12345";
Path dynamicOutput = Paths.get("output", userId, LocalDate.now().toString());
Files.createDirectories(dynamicOutput);
HtmlViewOptions dynamicOptions = HtmlViewOptions.forEmbeddedResources(dynamicOutput);

Các vấn đề thường gặp và khắc phục

Vấn đề 1: Lỗi “File Not Found”

Đảm bảo đường dẫn nhập là tuyệt đối hoặc tương đối so với thư mục làm việc, và kiểm tra quyền truy cập tệp. Sử dụng đối tượng Path giúp tránh các lỗi nối chuỗi thường gặp.

Vấn đề 2: Bình luận không xuất hiện trong đầu ra

Kiểm tra lại rằng setRenderComments(true) được gọi trước viewer.view(). Đồng thời xác nhận tài liệu nguồn thực sự chứa bình luận; bạn có thể kiểm tra qua viewer.getDocumentInfo().getComments().

Vấn đề 3: Lỗi Out of Memory với tài liệu lớn

GroupDocs Viewer truyền dữ liệu theo luồng, nhưng các tệp cực lớn (> 500 trang) vẫn có thể gây áp lực cho heap JVM. Tăng kích thước heap bằng -Xmx4g hoặc chỉ hiển thị các trang cần thiết.

Vấn đề 4: Hiệu năng hiển thị chậm

Hiển thị các phạm vi trang cụ thể bằng viewer.view(pageRange, viewOptions). Tài nguyên bên ngoài (forExternalResources()) cũng giảm kích thước payload HTML, tăng tốc độ tải trình duyệt.

Các mẫu triển khai thực tế

Mẫu 1: Tích hợp ứng dụng web

Tích hợp logic hiển thị vào controller Spring Boot để phục vụ HTML theo yêu cầu:

@RestController
@RequestMapping("/api/view")
public class DocumentController {

    @GetMapping("/{id}")
    public ResponseEntity<Resource> renderDocument(@PathVariable String id) throws IOException {
        Path docPath = Paths.get("documents", id + ".docx");
        Path outDir = Files.createTempDirectory("viewer");
        HtmlViewOptions options = HtmlViewOptions.forEmbeddedResources(outDir);
        options.setRenderComments(true);
        try (Viewer viewer = new Viewer(docPath.toFile())) {
            viewer.view(options);
        }
        // Return the first HTML page as a Resource
        Path firstPage = outDir.resolve("page_1.html");
        Resource resource = new UrlResource(firstPage.toUri());
        return ResponseEntity.ok()
                .contentType(MediaType.TEXT_HTML)
                .body(resource);
    }
}

Mẫu 2: Xử lý hàng loạt nhiều tài liệu

Khi cần chuyển đổi toàn bộ thư mục chứa các tệp Word, lặp qua thư mục và tái sử dụng cùng một thể hiện HtmlViewOptions để giảm thiểu việc tạo đối tượng mới.

Tối ưu hoá hiệu năng và các thực tiễn tốt nhất

Mẹo quản lý bộ nhớ

  • Luôn sử dụng try‑with‑resources cho các thể hiện Viewer.
  • Xử lý tài liệu lớn theo lô thay vì tải toàn bộ vào bộ nhớ một lúc.
  • Giám sát việc sử dụng heap JVM bằng các công cụ như VisualVM và điều chỉnh -Xmx khi cần.
  • Triển khai cache hợp lý cho các tài liệu truy cập thường xuyên để tránh việc render lặp lại.

Hướng dẫn sử dụng tài nguyên

Cho Ứng dụng Nhỏ (< 100 tài liệu/ngày):

HtmlViewOptions options = HtmlViewOptions.forEmbeddedResources(Paths.get("output"));
options.setRenderComments(true);

Cho Ứng dụng Lưu lượng Cao (1000+ tài liệu/ngày):

HtmlViewOptions options = HtmlViewOptions.forExternalResources(Paths.get("output"));
options.setRenderComments(true);
options.setCacheEnabled(true);

Chiến lược cache

Lưu trữ HTML đã render trong cache phân tán (ví dụ Redis) với khóa là hash của tài liệu. Khi nhận yêu cầu, kiểm tra cache trước; nếu có, trả ngay HTML đã cache, bỏ qua engine render.

Khi nào nên dùng GroupDocs Viewer so với các giải pháp thay thế

GroupDocs Viewer là lựa chọn hoàn hảo cho

  • Hệ thống Quản lý Tài liệu – cần hiển thị nhiều loại tệp với chú thích.
  • Nền tảng Đánh giá Cộng tác – bình luận phải luôn hiển thị cho mọi người tham gia.
  • Công cụ Giáo dục – ghi chú của giảng viên xuất hiện cùng slide bài giảng.
  • Ứng dụng Pháp lý – hợp đồng có bình luận của luật sư cần được render trung thực.

Xem xét các giải pháp thay thế khi

  • Hiển thị PDF đơn giản – trình duyệt có thể dùng trình xem PDF gốc.
  • Chuyển đổi ảnh cơ bảnImageIO hoặc các thư viện tương tự nhẹ hơn.
  • Trích xuất văn bản thuần – Apache POI hoặc iText có thể phù hợp hơn.

Câu hỏi thường gặp

Q: Tôi có thể render tài liệu mà không có bình luận không?
A: Có — chỉ cần bỏ qua lời gọi setRenderComments(true) hoặc đặt nó thành false.

Q: Những định dạng tệp nào hỗ trợ render bình luận?
A: Hầu hết các định dạng chính — bao gồm DOC/DOCX, XLS/XLSX, PPT/PPTX, PDF và nhiều hơn nữa. Xem tài liệu chính thức để biết danh sách đầy đủ.

Q: Tôi có thể tùy chỉnh kiểu dáng đầu ra HTML không?
A: Hoàn toàn có thể. Sử dụng HtmlViewOptions.setEmbedResources(false) để tạo các tệp CSS riêng, sau đó thêm stylesheet của bạn sau khi render.

Q: Làm sao xử lý tài liệu được bảo mật bằng mật khẩu?
A: Cung cấp một thể hiện LoadOptions kèm mật khẩu:

LoadOptions cho phép bạn chỉ định các tham số tải tài liệu như mật khẩu.

LoadOptions loadOptions = new LoadOptions("myPassword");
try (Viewer viewer = new Viewer(inputPath.toFile(), loadOptions)) {
    viewer.view(viewOptions);
}

Q: Có thể render chỉ các trang cụ thể không?
A: Có — sử dụng phương thức view có tham số bộ sưu tập PageNumber:

PageNumber đại diện cho chỉ số trang cụ thể khi render một tập hợp trang.

viewer.view(new int[]{1, 3, 5}, viewOptions);

Q: Tại sao render chậm với tài liệu lớn?
A: Các tệp lớn đòi hỏi thời gian xử lý nhiều hơn. Cải thiện tốc độ bằng cách render chỉ các trang cần, dùng tài nguyên bên ngoài, tăng heap JVM và bật xử lý bất đồng bộ.

Q: Làm sao theo dõi tiến độ render?
A: Mặc dù GroupDocs Viewer không có callback tích hợp, bạn có thể đo thời gian bằng System.nanoTime() trước và sau viewer.view() để ghi lại thời lượng.

Q: Điều gì xảy ra nếu tài liệu nguồn bị hỏng?
A: Thư viện sẽ ném ViewerException. Bọc lệnh trong khối try‑catch và ghi log lỗi để xử lý mềm mại.

Q: Tôi có thể dùng GroupDocs Viewer trong ứng dụng thương mại không?
A: Có, nhưng cần giấy phép thương mại. Bản dùng thử miễn phí có watermark phải được loại bỏ cho môi trường sản xuất.

Q: Có giới hạn sử dụng nào không?
A: Thư viện không đặt giới hạn, tuy nhiên hợp đồng giấy phép của bạn có thể quy định mức sử dụng tối đa. Kiểm tra chi tiết trong hợp đồng.

Q: Tôi có thể phân phối ứng dụng có tích hợp GroupDocs Viewer không?
A: Bạn có thể phân phối ứng dụng của mình, nhưng không được phân phối lại các binary của thư viện GroupDocs. Xem điều khoản giấy phép để tuân thủ.

Các bước tiếp theo và Chủ đề nâng cao

Bạn đã có nền tảng vững chắc để convert word to html đồng thời bảo lưu bình luận. Dưới đây là một số hướng để nâng cao kỹ năng:

  1. Thêm watermark – chèn watermark tùy chỉnh vào các trang render để thương hiệu hoặc bảo mật.
  2. Trích xuất metadata – lấy thông tin tác giả, ngày tạo, số trang qua viewer.getDocumentInfo().
  3. Trình xem tùy chỉnh – xây dựng trình xem chuyên biệt cho PDF, bảng tính hoặc slide, ẩn hoặc làm nổi bật bình luận theo cách riêng.
  4. Tích hợp lưu trữ đám mây – render trực tiếp từ AWS S3, Azure Blob hoặc Google Drive mà không cần tải về cục bộ.

Lộ trình học tập đề xuất

  1. Thử nghiệm với các loại tệp khác nhau – thử Excel, PowerPoint và PDF để xem cách bình luận được xử lý trên các định dạng.
  2. Xây dựng trình xem web đơn giản – tạo một trang HTML tối thiểu tải HTML đã render qua <iframe> hoặc AJAX.
  3. Khám phá hệ sinh thái GroupDocs – xem xét GroupDocs Annotation, Comparison và Signature để có quy trình tài liệu đầu‑cuối.
  4. Tham gia cộng đồng – tham gia Diễn đàn GroupDocs để nhận mẹo, dự án mẫu và hỗ trợ.

Nhận trợ giúp và hỗ trợ

Nguồn tài nguyên chính thức

Nguồn tài nguyên cộng đồng

  • Stack Overflow (tag: groupdocs-viewer)
  • Các cộng đồng lập trình trên Reddit
  • Máy chủ Discord dành cho nhà phát triển Java

Cập nhật lần cuối: 2026-05-21
Được kiểm tra với: GroupDocs.Viewer 25.2 for Java
Tác giả: GroupDocs

java -version
javac -version
mvn -version
mvn archetype:generate -DgroupId=com.example.documentviewer -DartifactId=groupdocs-viewer-demo -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
<repositories>
   <repository>
      <id>repository.groupdocs.com</id>
      <name>GroupDocs Repository</name>
      <url>https://releases.groupdocs.com/viewer/java/</url>
   </repository>
</repositories>
<dependencies>
   <dependency>
      <groupId>com.groupdocs</groupId>
      <artifactId>groupdocs-viewer</artifactId>
      <version>25.2</version>
   </dependency>
</dependencies>
import com.groupdocs.viewer.Viewer;

// The try-with-resources pattern ensures proper cleanup
try (Viewer viewer = new Viewer("path/to/your/document.docx")) {
    // All rendering operations happen here
    // Resources are automatically closed when done
} catch (Exception e) {
    System.err.println("Error rendering document: " + e.getMessage());
    e.printStackTrace();
}
import java.nio.file.Path;
import java.nio.file.Paths;

// Create a descriptive output directory
Path outputDirectory = Paths.get("rendered-documents");
Path pageFilePathFormat = outputDirectory.resolve("page_{0}.html");
import com.groupdocs.viewer.options.HtmlViewOptions;

// Create HTML options with embedded resources
HtmlViewOptions viewOptions = HtmlViewOptions.forEmbeddedResources(pageFilePathFormat);

// The crucial setting – enable comment rendering!
viewOptions.setRenderComments(true);
import com.groupdocs.viewer.Viewer;

try (Viewer viewer = new Viewer("path/to/your/document.docx")) {
    // Create output directory if it doesn't exist
    if (!outputDirectory.toFile().exists()) {
        outputDirectory.toFile().mkdirs();
    }
    
    // Perform the actual rendering
    viewer.view(viewOptions);
    
    System.out.println("Document rendered successfully!");
    System.out.println("Output location: " + outputDirectory.toAbsolutePath());
    
} catch (Exception e) {
    System.err.println("Rendering failed: " + e.getMessage());
    e.printStackTrace();
}
package com.example.documentviewer;

import com.groupdocs.viewer.Viewer;
import com.groupdocs.viewer.options.HtmlViewOptions;
import java.nio.file.Path;
import java.nio.file.Paths;

public class DocumentRenderer {
    
    public static void main(String[] args) {
        renderDocumentWithComments("sample-document.docx", "output");
    }
    
    public static void renderDocumentWithComments(String inputFile, String outputDir) {
        // Set up paths
        Path outputDirectory = Paths.get(outputDir);
        Path pageFilePathFormat = outputDirectory.resolve("page_{0}.html");
        
        // Configure rendering options
        HtmlViewOptions viewOptions = HtmlViewOptions.forEmbeddedResources(pageFilePathFormat);
        viewOptions.setRenderComments(true);
        
        // Render the document
        try (Viewer viewer = new Viewer(inputFile)) {
            // Ensure output directory exists
            outputDirectory.toFile().mkdirs();
            
            // Execute rendering
            viewer.view(viewOptions);
            
            System.out.println("✓ Document rendered with comments preserved");
            System.out.println("📂 Output directory: " + outputDirectory.toAbsolutePath());
            
        } catch (Exception e) {
            System.err.println("❌ Rendering failed: " + e.getMessage());
            e.printStackTrace();
        }
    }
}
import java.nio.file.Path;
import java.nio.file.Paths;

public class PathManager {
    
    /**
     * Creates a structured output path based on document name and timestamp
     */
    public static Path getOutputDirectoryPath(String documentName) {
        String timestamp = String.valueOf(System.currentTimeMillis());
        String cleanDocName = documentName.replaceAll("[^a-zA-Z0-9]", "_");
        
        return Paths.get("rendered-docs")
                   .resolve(cleanDocName)
                   .resolve(timestamp);
    }
    
    /**
     * Simple output directory for basic use cases
     */
    public static Path getSimpleOutputPath(String folderName) {
        return Paths.get("output").resolve(folderName);
    }
}
// Always check if file exists before processing
Path inputPath = Paths.get("your-document.docx");
if (!inputPath.toFile().exists()) {
    throw new IllegalArgumentException("Input file not found: " + inputPath.toAbsolutePath());
}

// Check if file is readable
if (!inputPath.toFile().canRead()) {
    throw new IllegalArgumentException("Cannot read input file: " + inputPath.toAbsolutePath());
}
HtmlViewOptions viewOptions = HtmlViewOptions.forEmbeddedResources(pageFilePathFormat);
// This line is crucial – don't forget it!
viewOptions.setRenderComments(true);

// For debugging, you can verify the setting:
System.out.println("Comments enabled: " + viewOptions.isRenderComments());
// Increase JVM heap size when running
// java -Xmx2g -Xms1g YourApplication

// Or process documents page by page for very large files
HtmlViewOptions viewOptions = HtmlViewOptions.forEmbeddedResources(pageFilePathFormat);
viewOptions.setRenderComments(true);

// Render only specific pages if needed
viewer.view(viewOptions, 1, 2, 3); // Renders only pages 1, 2, and 3
// Use external resources for faster processing of multiple pages
HtmlViewOptions viewOptions = HtmlViewOptions.forExternalResources(
    pageFilePathFormat, 
    "resources/page_{0}/", 
    "resources/page_{0}/{0}"
);

// Enable caching if processing the same document multiple times
// (Note: Implement caching at application level)
@RestController
@RequestMapping("/api/documents")
public class DocumentController {
    
    @PostMapping("/render")
    public ResponseEntity<String> renderDocument(
            @RequestParam("file") MultipartFile file) {
        
        try {
            // Save uploaded file temporarily
            Path tempFile = Files.createTempFile("upload", ".tmp");
            file.transferTo(tempFile.toFile());
            
            // Render with comments
            String outputDir = renderDocumentWithComments(
                tempFile.toString(), 
                "web-output"
            );
            
            return ResponseEntity.ok("Document rendered: " + outputDir);
            
        } catch (Exception e) {
            return ResponseEntity.badRequest()
                .body("Rendering failed: " + e.getMessage());
        }
    }
}
public class BatchDocumentProcessor {
    
    public void processFolderWithComments(String inputFolder) {
        File folder = new File(inputFolder);
        File[] files = folder.listFiles((dir, name) -> 
            name.toLowerCase().endsWith(".docx") || 
            name.toLowerCase().endsWith(".xlsx") ||
            name.toLowerCase().endsWith(".pptx")
        );
        
        if (files == null) return;
        
        for (File file : files) {
            try {
                String outputDir = file.getName().replace(".", "_") + "_output";
                renderDocumentWithComments(file.getAbsolutePath(), outputDir);
                System.out.println("✓ Processed: " + file.getName());
                
            } catch (Exception e) {
                System.err.println("❌ Failed to process " + file.getName() + ": " + e.getMessage());
            }
        }
    }
}
// Simple approach works fine
try (Viewer viewer = new Viewer(documentPath)) {
    viewer.view(viewOptions);
}
public class DocumentRenderingService {
    private final ExecutorService executorService = 
        Executors.newFixedThreadPool(4); // Limit concurrent renderings
    
    public CompletableFuture<String> renderAsync(String documentPath) {
        return CompletableFuture.supplyAsync(() -> {
            try (Viewer viewer = new Viewer(documentPath)) {
                // Rendering logic here
                return "success";
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }, executorService);
    }
}
public class CachedDocumentRenderer {
    private final Map<String, String> renderCache = new ConcurrentHashMap<>();
    
    public String renderWithCaching(String documentPath) {
        String cacheKey = generateCacheKey(documentPath);
        
        return renderCache.computeIfAbsent(cacheKey, key -> {
            // Only render if not already cached
            return performActualRendering(documentPath);
        });
    }
    
    private String generateCacheKey(String documentPath) {
        // Include file modification time in cache key
        File file = new File(documentPath);
        return documentPath + "_" + file.lastModified();
    }
}
LoadOptions loadOptions = new LoadOptions();
loadOptions.setPassword("your-password");
try (Viewer viewer = new Viewer("protected-doc.docx", loadOptions)) {
    // Render as usual
}
viewer.view(viewOptions, 1, 3, 5); // Renders only pages 1, 3, and 5
System.out.println("Starting render for: " + documentName);
long startTime = System.currentTimeMillis();
viewer.view(viewOptions);
long endTime = System.currentTimeMillis();
System.out.println("Rendering completed in: " + (endTime - startTime) + "ms");
try (Viewer viewer = new Viewer(documentPath)) {
    viewer.view(viewOptions);
} catch (CorruptOrDamagedFileException e) {
    System.err.println("Document is corrupted: " + e.getMessage());
} catch (Exception e) {
    System.err.println("General error: " + e.getMessage());
}

Các hướng dẫn liên quan