feat(oo): docs pdf --stream/--pipe (converted bytes to stdout)

This commit is contained in:
2026-09-22 22:41:14 +01:00
parent 4515a88fe8
commit 7c089a6439
2 changed files with 32 additions and 12 deletions
+1
View File
@@ -620,6 +620,7 @@ oo link 3684 3694 # DocEditor URL for file ids (title + u
oo docs presigned 3684 # short-lived fetchable URL of an OO file
oo docs pdf 3684 --out out.pdf # OO file → PDF (via DocumentServer)
oo docs pdf ./report.docx --to pdf # local file → PDF on the fly (temp upload+cleanup)
oo docs pdf 3684 --stream > out.pdf # pipe: bytes to stdout (alias --pipe)
# export ONLYOFFICE_DS_SECRET=<DocumentServer CoAuthoring secret>
# docs base: $ONLYOFFICE_DOCS_URL, else $ONLYOFFICE_URL + /ds-vpath
+22 -3
View File
@@ -3,6 +3,7 @@ package main
import (
"context"
"fmt"
"io"
"os"
"path/filepath"
"strconv"
@@ -67,6 +68,7 @@ func docsToolsCmd() *cobra.Command {
func docsPDFCmd() *cobra.Command {
var out, docsURL, secret, output, folder string
var stream, pipe bool
cmd := &cobra.Command{
Use: "pdf FILE_ID | PATH [ARG...]",
Short: "Convert files to PDF via the DocumentServer converter (OO file ids or local paths)",
@@ -104,6 +106,10 @@ $ONLYOFFICE_DS_SECRET (DocumentServer services.CoAuthoring.secret).`,
if ot == "" {
ot = "pdf"
}
toStdout := stream || pipe
if toStdout && len(args) > 1 {
return fmt.Errorf("--stream/--pipe writes one file to stdout; pass a single input")
}
for _, arg := range args {
id, local := arg, false
title := ""
@@ -135,7 +141,11 @@ $ONLYOFFICE_DS_SECRET (DocumentServer services.CoAuthoring.secret).`,
if err != nil {
return fmt.Errorf("convert %s: %w", id, err)
}
var w io.Writer
dst := out
if toStdout {
w = os.Stdout
} else {
if dst == "" {
stem := strings.TrimSuffix(title, filepath.Ext(title))
if stem == "" {
@@ -143,12 +153,14 @@ $ONLYOFFICE_DS_SECRET (DocumentServer services.CoAuthoring.secret).`,
}
dst = stem + "." + ot
}
f, err := os.Create(dst)
fh, err := os.Create(dst)
if err != nil {
return err
}
n, derr := c.DownloadURLTo(cmd.Context(), res.FileURL, f)
f.Close()
w = fh
defer fh.Close()
}
n, derr := c.DownloadURLTo(cmd.Context(), res.FileURL, w)
if local {
// Best-effort cleanup of the temporary upload.
if nid, e := strconv.Atoi(id); e == nil {
@@ -158,8 +170,13 @@ $ONLYOFFICE_DS_SECRET (DocumentServer services.CoAuthoring.secret).`,
if derr != nil {
return fmt.Errorf("download: %w", derr)
}
if toStdout {
// Keep stdout byte-clean for pipes; status goes to stderr.
fmt.Fprintf(os.Stderr, "converted %s -> stdout (%d bytes, %s)\n", arg, n, ot)
} else {
printObject(map[string]any{"source": arg, "fileid": id, "title": title, "output": dst, "bytes": n, "type": ot})
}
}
return nil
},
}
@@ -168,6 +185,8 @@ $ONLYOFFICE_DS_SECRET (DocumentServer services.CoAuthoring.secret).`,
cmd.Flags().StringVar(&docsURL, "docs-url", "", "DocumentServer base (default $ONLYOFFICE_DOCS_URL or $ONLYOFFICE_URL/ds-vpath)")
cmd.Flags().StringVar(&secret, "secret", "", "JWT secret (default $ONLYOFFICE_DS_SECRET)")
cmd.Flags().StringVar(&folder, "folder", "2", "scratch folder id for local-file uploads")
cmd.Flags().BoolVar(&stream, "stream", false, "write the converted bytes to stdout (pipe-friendly)")
cmd.Flags().BoolVar(&pipe, "pipe", false, "alias for --stream")
return cmd
}