mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-10-30 01:27:26 +08:00
This commit is contained in:
1 parent
651e3cf5b5
commit
fb3a9e8148
3 files changed
+75
-13
No files matched your search
+10
-9
@@ -695,7 +695,7 @@ async function loadWASM() {
|
|||||||
setProgress("正在保存", null);
|
setProgress("正在保存", null);
|
||||||
} else if (!el.cancelExportButton.disabled) {
|
} else if (!el.cancelExportButton.disabled) {
|
||||||
if (data.completed === data.total) {
|
if (data.completed === data.total) {
|
||||||
setProgress("正在封装", null);
|
setProgress("正在收尾", null);
|
||||||
} else {
|
} else {
|
||||||
setProgress(`正在导出 ${data.completed} / ${data.total} 页`, data.completed / data.total * 100);
|
setProgress(`正在导出 ${data.completed} / ${data.total} 页`, data.completed / data.total * 100);
|
||||||
}
|
}
|
||||||
@@ -1540,7 +1540,7 @@ async function downloadAttachment(attachment) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
downloadBytes(result.bytes, "application/octet-stream", attachment.fileName);
|
downloadBytes(result.bytes, "application/octet-stream", attachment.fileName);
|
||||||
setStatus(`附件下载完成 ${formatBytes(result.bytes.length, "0 KB")}`);
|
setStatus(`附件下载完成 ${formatBytes(result.bytes.length)}`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (openSeq === state.openSeq) {
|
if (openSeq === state.openSeq) {
|
||||||
showError(err, false);
|
showError(err, false);
|
||||||
@@ -1600,9 +1600,10 @@ async function exportFile(whole, indices = null) {
|
|||||||
if (!format) {
|
if (!format) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const label = whole ? (format.value === "pdf" ? "PDF" : "ZIP") : format.label;
|
const archive = whole && format.value !== "pdf" && format.value !== "txt";
|
||||||
const extension = whole ? label.toLowerCase() : format.extension;
|
const label = archive ? "ZIP" : format.label;
|
||||||
const mime = whole && format.value !== "pdf" ? "application/zip" : format.mime;
|
const extension = archive ? "zip" : format.extension;
|
||||||
|
const mime = archive ? "application/zip" : format.mime;
|
||||||
const openSeq = state.openSeq;
|
const openSeq = state.openSeq;
|
||||||
const fileName = whole ? `${baseFileName()}.${extension}` : pageFileName(extension);
|
const fileName = whole ? `${baseFileName()}.${extension}` : pageFileName(extension);
|
||||||
const pageIndex = state.pageIndex;
|
const pageIndex = state.pageIndex;
|
||||||
@@ -1627,7 +1628,7 @@ async function exportFile(whole, indices = null) {
|
|||||||
if (result.blob) {
|
if (result.blob) {
|
||||||
downloadBytes(result.blob, result.mime, fileName);
|
downloadBytes(result.blob, result.mime, fileName);
|
||||||
}
|
}
|
||||||
setStatus(`${result.label} 导出完成 ${formatBytes(result.size, result.label)}`);
|
setStatus(`${result.label} 导出完成 ${formatBytes(result.size)}`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (openSeq === state.openSeq) {
|
if (openSeq === state.openSeq) {
|
||||||
if (err.name === "AbortError") {
|
if (err.name === "AbortError") {
|
||||||
@@ -2737,7 +2738,7 @@ function renderAttachments() {
|
|||||||
name.className = "attachment-name";
|
name.className = "attachment-name";
|
||||||
name.textContent = attachment.name;
|
name.textContent = attachment.name;
|
||||||
item.append(name);
|
item.append(name);
|
||||||
const detail = [attachment.format, attachment.size == null ? "" : formatBytes(attachment.size * 1024, "0 KB")].filter(Boolean).join(" · ");
|
const detail = [attachment.format, attachment.size == null ? "" : formatBytes(attachment.size * 1024)].filter(Boolean).join(" · ");
|
||||||
if (detail) {
|
if (detail) {
|
||||||
const meta = document.createElement("span");
|
const meta = document.createElement("span");
|
||||||
meta.className = "attachment-detail";
|
meta.className = "attachment-detail";
|
||||||
@@ -3524,9 +3525,9 @@ function currentImageDPI() {
|
|||||||
return Number.parseFloat(el.imageDPI.value) || DEFAULT_IMAGE_DPI;
|
return Number.parseFloat(el.imageDPI.value) || DEFAULT_IMAGE_DPI;
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatBytes(size, fallback = "PDF") {
|
function formatBytes(size) {
|
||||||
if (!Number.isFinite(size) || size <= 0) {
|
if (!Number.isFinite(size) || size <= 0) {
|
||||||
return fallback;
|
return "0 KB";
|
||||||
}
|
}
|
||||||
if (size < 1024 * 1024) {
|
if (size < 1024 * 1024) {
|
||||||
return `${Math.round(size / 1024)} KB`;
|
return `${Math.round(size / 1024)} KB`;
|
||||||
|
|||||||
@@ -179,7 +179,8 @@ var supportedExportFormats = []ExportFormat{
|
|||||||
{Value: "pdf", Label: "PDF", Extension: "pdf", MIME: "application/pdf"},
|
{Value: "pdf", Label: "PDF", Extension: "pdf", MIME: "application/pdf"},
|
||||||
{Value: "eps", Label: "EPS", Extension: "eps", MIME: "application/postscript"},
|
{Value: "eps", Label: "EPS", Extension: "eps", MIME: "application/postscript"},
|
||||||
{Value: "png", Label: "PNG", Extension: "png", MIME: "image/png"},
|
{Value: "png", Label: "PNG", Extension: "png", MIME: "image/png"},
|
||||||
{Value: "jpg", Label: "JPEG", Extension: "jpg", MIME: "image/jpeg"},
|
{Value: "jpg", Label: "JPG", Extension: "jpg", MIME: "image/jpeg"},
|
||||||
|
{Value: "txt", Label: "TXT", Extension: "txt", MIME: "text/plain"},
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExportFormats 获取导出格式
|
// ExportFormats 获取导出格式
|
||||||
@@ -631,7 +632,7 @@ func signatureStampInfos(positions []ofdgo.SignatureStampPosition) []SignatureSt
|
|||||||
return infos
|
return infos
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExportDocument 导出文档为PDF或逐页打包ZIP
|
// ExportDocument 导出文档为PDF、TXT或逐页打包ZIP
|
||||||
// 入参: value 导出格式, dpi 图片DPI, writer 输出流, indices 零基页面索引,省略则全部
|
// 入参: value 导出格式, dpi 图片DPI, writer 输出流, indices 零基页面索引,省略则全部
|
||||||
// 返回: ExportFormat 导出格式, error 错误信息
|
// 返回: ExportFormat 导出格式, error 错误信息
|
||||||
func (s *Session) ExportDocument(value string, dpi float64, writer io.Writer, indices ...int) (ExportFormat, error) {
|
func (s *Session) ExportDocument(value string, dpi float64, writer io.Writer, indices ...int) (ExportFormat, error) {
|
||||||
@@ -645,6 +646,9 @@ func (s *Session) ExportDocument(value string, dpi float64, writer io.Writer, in
|
|||||||
if s == nil || s.Reader == nil || s.Renderer == nil || s.doc == nil {
|
if s == nil || s.Reader == nil || s.Renderer == nil || s.doc == nil {
|
||||||
return ExportFormat{}, fmt.Errorf("ofd document is not opened")
|
return ExportFormat{}, fmt.Errorf("ofd document is not opened")
|
||||||
}
|
}
|
||||||
|
if format.Value == "txt" {
|
||||||
|
return format, s.Renderer.RenderToMultiPageText(writer, indices...)
|
||||||
|
}
|
||||||
renderer := *s.Renderer
|
renderer := *s.Renderer
|
||||||
if dpi > 0 && (format.Value == "png" || format.Value == "jpg") {
|
if dpi > 0 && (format.Value == "png" || format.Value == "jpg") {
|
||||||
renderer.DPI = dpi
|
renderer.DPI = dpi
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// RenderTo 按格式渲染单页,JPEG使用95画质
|
// RenderTo 按格式渲染单页,JPEG使用95画质
|
||||||
// 入参: page 页面内容, writer 输出流, format svg、pdf、eps、png、jpg或jpeg
|
// 入参: page 页面内容, writer 输出流, format svg、pdf、eps、png、jpg、jpeg或txt
|
||||||
// 返回: error 错误信息
|
// 返回: error 错误信息
|
||||||
func (r *Renderer) RenderTo(page *PageContent, writer io.Writer, format string) error {
|
func (r *Renderer) RenderTo(page *PageContent, writer io.Writer, format string) error {
|
||||||
_, render, err := r.outputRenderer(format)
|
_, render, err := r.outputRenderer(format)
|
||||||
@@ -55,6 +55,8 @@ func (r *Renderer) outputRenderer(format string) (string, func(*PageContent, io.
|
|||||||
return "svg", r.RenderToSVG, nil
|
return "svg", r.RenderToSVG, nil
|
||||||
case "pdf":
|
case "pdf":
|
||||||
return "pdf", r.RenderToPDF, nil
|
return "pdf", r.RenderToPDF, nil
|
||||||
|
case "txt":
|
||||||
|
return "txt", r.RenderToText, nil
|
||||||
case "eps":
|
case "eps":
|
||||||
return "eps", r.RenderToEPS, nil
|
return "eps", r.RenderToEPS, nil
|
||||||
case "png":
|
case "png":
|
||||||
@@ -69,7 +71,7 @@ func (r *Renderer) outputRenderer(format string) (string, func(*PageContent, io.
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RenderToZIP 逐页渲染并写入ZIP,文件编号按总页数补零,出错时调用方应丢弃输出
|
// RenderToZIP 逐页渲染并写入ZIP,文件编号按总页数补零,出错时调用方应丢弃输出
|
||||||
// 入参: writer 输出流, format svg、pdf、eps、png、jpg或jpeg, indices 零基页面索引,省略则全部,按原页序去重
|
// 入参: writer 输出流, format svg、pdf、eps、png、jpg、jpeg或txt, indices 零基页面索引,省略则全部,按原页序去重
|
||||||
// 返回: error 错误信息
|
// 返回: error 错误信息
|
||||||
func (r *Renderer) RenderToZIP(writer io.Writer, format string, indices ...int) error {
|
func (r *Renderer) RenderToZIP(writer io.Writer, format string, indices ...int) error {
|
||||||
extension, render, err := r.outputRenderer(format)
|
extension, render, err := r.outputRenderer(format)
|
||||||
@@ -115,6 +117,61 @@ func (r *Renderer) RenderToZIP(writer io.Writer, format string, indices ...int)
|
|||||||
return archive.Close()
|
return archive.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RenderToText 导出页面原文为UTF-8文本,以换行分隔非空文本对象
|
||||||
|
// 入参: page 页面内容, writer 输出流
|
||||||
|
// 返回: error 错误信息
|
||||||
|
func (r *Renderer) RenderToText(page *PageContent, writer io.Writer) error {
|
||||||
|
text, err := r.PageText(page)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = io.WriteString(writer, text.String())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// RenderToMultiPageText 逐页导出UTF-8原文,以换行分隔非空页面,出错时调用方应丢弃输出
|
||||||
|
// 入参: writer 输出流, indices 零基页面索引,省略则全部,按原页序去重
|
||||||
|
// 返回: error 错误信息
|
||||||
|
func (r *Renderer) RenderToMultiPageText(writer io.Writer, indices ...int) error {
|
||||||
|
count, err := r.Reader.PageCount()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
indices, err = exportPageIndices(count, indices)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := r.exportProgress(0, len(indices)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
written := false
|
||||||
|
for i, index := range indices {
|
||||||
|
page, err := r.Reader.PageContentByIndex(index)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to read page %d: %w", index+1, err)
|
||||||
|
}
|
||||||
|
text, err := r.PageText(page)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to extract page %d text: %w", index+1, err)
|
||||||
|
}
|
||||||
|
if value := text.String(); value != "" {
|
||||||
|
if written {
|
||||||
|
if _, err := io.WriteString(writer, "\n"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if _, err := io.WriteString(writer, value); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
written = true
|
||||||
|
}
|
||||||
|
if err := r.exportProgress(i+1, len(indices)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// exportProgress 回报导出进度并传递调用方的停止原因
|
// exportProgress 回报导出进度并传递调用方的停止原因
|
||||||
// 入参: completed 已处理页数, total 总页数
|
// 入参: completed 已处理页数, total 总页数
|
||||||
// 返回: error 停止原因
|
// 返回: error 停止原因
|
||||||
|
|||||||
Reference in new issue
Block a user