Article:
Chuyển từ HTML sang PDF trong Ruby
2808
ngocdaothanh.myopenid.com 172Updated 5 months ago |
Mục lục rất hữu ích, nó giúp người đọc mường tượng được "cấu trúc", viết nên đọc cái gì trước cái gì sau. Mục lục là thành phần (tính năng) quan trọng của OpenKH, chỉ nên đưa link đến bài viết có giá trị hoặc liên kết ngoài hay vào mục lục.
Chúng tôi muốn thêm tính năng cho OpenKH để từ nội dung trong mục lục xuất bản thành sách PDF hiển thị được chữ tiếng Việt nói riêng và bất kì ngôn ngữ nào khác nói chung (OpenKH dùng Ruby-Gettext nên chỉ mất chừng 30 phút để chuyển ngữ, hiện đã có 3 thứ tiếng: Anh, Việt, Nhật). Bài viết này trình bày những biện pháp chúng tôi đã tìm hiểu để đạt mục đích trên. Rất hoan nghênh mọi góp ý của các bạn.
Nguyên lí của qui trình chuyển từ HTML sang PDF
Giống như Tex, chuẩn PDF qui định rất chính xác font chữ, vị trí chữ, ảnh... tất tần tật mọi tham số ảnh hưởng đến việc hiển thị. Tài liệu khi mang ra 100 tiệm để in, thì cả 100 đều giống hệt nhau.
HTML không qui định ngặt nghèo vậy (đây được coi là bí quyết thành công của định dạng HTML), tuy nhiên trang web này xem trên IE khác trên Firefox khác trên Safari phải không ạ?
Về nguyên lí, hàm của các thư viện cho phép tạo PDF đều chỉ có dạng kiểu writeText(x, y, ...), có nghĩa phải tự định nghĩa chính xác dòng chữ nằm ở đâu, cỡ chữ bao nhiêu... Do đó, từ chuỗi kí tự HTML, ta phải parse thành dạng có cấu trúc, rồi ứng với từng phần tử của cấu trúc, gọi hàm vẽ thích hợp. Nếu may mắn có thư viện nào cho phép nhét HTML vào một phát ra được ngay PDF, chẳng qua nó tích hợp sẵn đoạn xử lí ở trên mà thôi.
Tìm hiểu thư viện
Điểm xuất phát là trang wiki của Ruby on Rails. Dưới đây là đánh giá các giải pháp được nêu sau khi đã kiểm nghiệm bằng cách viết thử chương trình.
HTMLDOC
Rất tiện, chỉ 1 dòng lệnh là đạt được mục tiêu. Rất tiếc v1.8 chưa hỗ trợ Unicode và CSS. v1.9 đang được phát triển, có hỗ trợ CSS và một chút UTF-8, các ngôn ngữ châu Á chưa được hỗ trợ.
PdfWriter
Có vẻ sơ sài, chưa thử nghiệm
PDF::Writer
Thư viện tốt nhất Ruby có được hiện nay, nhưng rất tiếc tác giả tuyên bố sẽ không bao giờ hỗ trợ UTF-8 vì chuẩn do Adobe công bố không hỗ trợ UTF-8. Ngoài ra, tác giả tiết lộ sắp lấy vợ, nên việc thêm UTF-16 đang bị trì hoãn.
Có patch để hiện được tiếng Nhật (Nhật giỏi thật
). Anh em nào muốn thể hiện, thay vì đi cua gái xin thử đi biểu tình à quên viết patch cho tiếng Việt xem sao.
Ruby FPDF
Mất tiền, cỡ 50 triệu VND, nên tất nhiên mọi nhu cầu đều được thỏa mãn.
Rfpdf
Viết lại từ thư viện PHP có sẵn. Xuất được Unicode nhưng code quá xấu, bug tùm lum.
Prawn
Có lẽ là giải pháp tốt nhất thuần Ruby. Có bài giới thiệu ở InfoQ.
JasperReports, iText
2 đại gia này thì khỏi chê, đã stable và tài liệu hướng dẫn có cả ebook vài trăm trang.
Dùng Cần dùng JRuby hoặc Rjb để chương trình Ruby và thư viện Java giao tiếp được với nhau. Rất khả thi.
Ví dụ dùng Rjb với iText:
- Cài Rjb: gem install rjb, trên Linux chú ý cần có biến môi trường JAVA_HOME
- Tải thư viện .jar (1 tập tin duy nhất) của iText về
- Tạo chương trình Ruby, để cùng thư mục với thư viện .jar trên
require 'rubygems'
require 'rjb'
Rjb::load(classpath = '.', jvmargs=[])
FileOutputStream = Rjb::import('java.io.FileOutputStream')
PdfWriter = Rjb::import('com.lowagie.text.pdf.PdfWriter')
Document = Rjb::import('com.lowagie.text.Document')
BaseFont = Rjb::import('com.lowagie.text.pdf.BaseFont')
Font = Rjb::import('com.lowagie.text.Font')
Paragraph = Rjb::import('com.lowagie.text.Paragraph')
document = Document.new()
PdfWriter.getInstance(document, FileOutputStream.new('Hello.pdf'))
bf = BaseFont.createFont('c:/windows/fonts/arial.ttf',
BaseFont.IDENTITY_H, BaseFont.EMBEDDED)
font = Font.new(bf, 12)
document.open
document.add(Paragraph.new('Tiếng Việt', font))
document.close
Chỉ cần vài dòng là thu được Hello.pdf. Chú ý cần nhúng phông chữ thì mới hiện được tiếng Việt.
Thư viện Flying Saucer rất tiện cho mục đích này, nó dựa trên iText.
172
Updated over 3 years ago
Updated over 3 years ago
5 months ago