mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-10-29 16:59:27 +08:00
This commit is contained in:
1 parent
fb3a9e8148
commit
6525b01bab
4 files changed
+50
-15
No files matched your search
+17
-5
@@ -1535,18 +1535,30 @@ async function downloadAttachment(attachment) {
|
||||
updateControls();
|
||||
setBusy(true, "正在读取附件", null, "正在读取附件");
|
||||
try {
|
||||
const result = await callWASM("ofdgoAttachmentData", attachment.id);
|
||||
const file = window.showSaveFilePicker ? await window.showSaveFilePicker({ suggestedName: attachment.fileName }) : null;
|
||||
if (openSeq !== state.openSeq) {
|
||||
return;
|
||||
}
|
||||
downloadBytes(result.bytes, "application/octet-stream", attachment.fileName);
|
||||
setStatus(`附件下载完成 ${formatBytes(result.bytes.length)}`);
|
||||
const result = await callWASM("ofdgoExportAttachment", attachment.id, file);
|
||||
if (openSeq !== state.openSeq) {
|
||||
return;
|
||||
}
|
||||
if (result.blob) {
|
||||
downloadBytes(result.blob, result.mime, attachment.fileName);
|
||||
}
|
||||
setStatus(`附件下载完成 ${formatBytes(result.size)}`);
|
||||
} catch (err) {
|
||||
if (openSeq === state.openSeq) {
|
||||
showError(err, false);
|
||||
if (err.name === "AbortError") {
|
||||
setStatus("下载已取消");
|
||||
} else {
|
||||
showError(err, false);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
state.exporting = false;
|
||||
state.exportRequestID = 0;
|
||||
el.cancelExportButton.hidden = true;
|
||||
if (openSeq === state.openSeq) {
|
||||
setBusy(false);
|
||||
updateControls();
|
||||
@@ -3416,7 +3428,7 @@ async function callWASM(name, ...args) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const id = ++wasmRequestID;
|
||||
wasmRequests.set(id, { resolve, reject, openSeq: state.openSeq });
|
||||
if (name === "ofdgoExportPage" || name === "ofdgoExportDocument") {
|
||||
if (name === "ofdgoExportPage" || name === "ofdgoExportDocument" || name === "ofdgoExportAttachment") {
|
||||
state.exportRequestID = id;
|
||||
el.cancelExportButton.hidden = false;
|
||||
el.cancelExportButton.disabled = false;
|
||||
|
||||
@@ -7,7 +7,7 @@ self.onmessage = ({ data }) => {
|
||||
exports.get(data.id)?.abort();
|
||||
return;
|
||||
}
|
||||
if (data.name === "ofdgoExportPage" || data.name === "ofdgoExportDocument") {
|
||||
if (data.name === "ofdgoExportPage" || data.name === "ofdgoExportDocument" || data.name === "ofdgoExportAttachment") {
|
||||
exports.set(data.id, new AbortController());
|
||||
}
|
||||
pending = pending.then(() => handleMessage(data));
|
||||
|
||||
+16
-5
@@ -21,6 +21,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"syscall/js"
|
||||
|
||||
"github.com/xiaoqidun/ofdgo"
|
||||
@@ -81,7 +82,6 @@ func RunWASM() {
|
||||
registerCallback("ofdgoOpen", openDocument)
|
||||
registerCallback("ofdgoConfigure", configureDocument)
|
||||
registerCallback("ofdgoDocumentInfo", documentInfo)
|
||||
registerCallback("ofdgoAttachmentData", attachmentData)
|
||||
registerCallback("ofdgoRenderPage", renderPage)
|
||||
registerCallback("ofdgoSVGFontData", svgFontData)
|
||||
registerCallback("ofdgoSearchPage", searchPage)
|
||||
@@ -90,6 +90,7 @@ func RunWASM() {
|
||||
registerCallback("ofdgoParsePageRange", parsePageRange)
|
||||
registerExportCallback("ofdgoExportPage", exportPage)
|
||||
registerExportCallback("ofdgoExportDocument", exportDocument)
|
||||
registerExportCallback("ofdgoExportAttachment", exportAttachment)
|
||||
registerCallback("ofdgoMatchFontFiles", matchFontFiles)
|
||||
select {}
|
||||
}
|
||||
@@ -207,18 +208,28 @@ func documentInfo(args []js.Value) (any, error) {
|
||||
return currentSession.Info(), nil
|
||||
}
|
||||
|
||||
// attachmentData 读取附件数据
|
||||
// exportAttachment 分块导出附件
|
||||
// 入参: args 浏览器参数
|
||||
// 返回: any 附件数据, error 错误信息
|
||||
func attachmentData(args []js.Value) (any, error) {
|
||||
func exportAttachment(args []js.Value) (any, error) {
|
||||
if currentSession == nil {
|
||||
return nil, fmt.Errorf("ofd document is not opened")
|
||||
}
|
||||
data, err := currentSession.Reader.AttachmentData(args[0].String())
|
||||
stream, err := currentSession.Reader.OpenAttachment(args[0].String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return successResult(map[string]any{"bytes": bytesToJS(data)}), nil
|
||||
defer stream.Close()
|
||||
writer := bufio.NewWriterSize(exportWriter{write: args[1]}, 1<<20)
|
||||
if _, err := io.Copy(writer, stream); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := writer.Flush(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return successResult(map[string]any{
|
||||
"mime": "application/octet-stream",
|
||||
}), nil
|
||||
}
|
||||
|
||||
// svgFontData 读取SVG字体资源
|
||||
|
||||
+16
-4
@@ -543,22 +543,34 @@ func (r *Reader) Attachments() ([]Attachment, error) {
|
||||
return doc.Attachments.Attachment, nil
|
||||
}
|
||||
|
||||
// AttachmentData 获取附件文件数据
|
||||
// OpenAttachment 打开附件文件流,调用方负责关闭,完整读取后校验ZIP数据
|
||||
// 入参: id 附件标识
|
||||
// 返回: []byte 附件数据, error 错误信息
|
||||
func (r *Reader) AttachmentData(id string) ([]byte, error) {
|
||||
// 返回: io.ReadCloser 附件文件流, error 错误信息
|
||||
func (r *Reader) OpenAttachment(id string) (io.ReadCloser, error) {
|
||||
attachments, err := r.Attachments()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, attachment := range attachments {
|
||||
if attachment.ID == id {
|
||||
return r.ResData(attachment.FileLoc)
|
||||
return r.openFile(r.ResPath(attachment.FileLoc))
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("attachment not found: %s", id)
|
||||
}
|
||||
|
||||
// AttachmentData 获取附件文件数据
|
||||
// 入参: id 附件标识
|
||||
// 返回: []byte 附件数据, error 错误信息
|
||||
func (r *Reader) AttachmentData(id string) ([]byte, error) {
|
||||
stream, err := r.OpenAttachment(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer stream.Close()
|
||||
return io.ReadAll(stream)
|
||||
}
|
||||
|
||||
// CustomTags 获取自定义标引
|
||||
// 返回: []CustomTag 自定义标引列表, error 错误信息
|
||||
func (r *Reader) CustomTags() ([]CustomTag, error) {
|
||||
|
||||
Reference in new issue
Block a user