mirror of
https://github.com/gotenberg/gotenberg.git
synced 2026-08-17 04:32:15 +01:00
feat(libreoffice): preserve filenames for zipped files instead of using randomly generated UUID filenames (#793)
* feat(libreoffice): preserve filenames for zipped files instead of using generated UUID filenames * chore: move github.com/google/uuid back to its original line * fix: add libreoffice/routes.go to PR
This commit is contained in:
committed by
Julien Neuhart
parent
e6d7131701
commit
089f161d1e
@@ -191,10 +191,18 @@ func (ctx *Context) FormData() *FormData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GeneratePath generates a path within the context's working directory. It
|
// GeneratePath generates a path within the context's working directory. It does not create a file.
|
||||||
// does not create a file.
|
// It either generates a new UUID-based filename or uses the provided filename.
|
||||||
func (ctx *Context) GeneratePath(extension string) string {
|
func (ctx *Context) GeneratePath(extension string, optionalFilename ...string) string {
|
||||||
return fmt.Sprintf("%s/%s%s", ctx.dirPath, uuid.New(), extension)
|
var filename string
|
||||||
|
if len(optionalFilename) > 0 {
|
||||||
|
// Use the provided filename
|
||||||
|
filename = optionalFilename[0]
|
||||||
|
} else {
|
||||||
|
// Generate a new UUID-based filename
|
||||||
|
filename = uuid.New().String()
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s/%s%s", ctx.dirPath, filename, extension)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddOutputPaths adds the given paths. Those paths will be used later to build
|
// AddOutputPaths adds the given paths. Those paths will be used later to build
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
|
|
||||||
@@ -51,10 +53,24 @@ func convertRoute(libreOffice libreofficeapi.Uno, engine gotenberg.PdfEngine) ap
|
|||||||
PdfUa: pdfua,
|
PdfUa: pdfua,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We need to check and see if there are any duplicate filenames in inputPaths.
|
||||||
|
filenameCounts := make(map[string]int)
|
||||||
|
for _, path := range inputPaths {
|
||||||
|
filename := strings.TrimSuffix(filepath.Base(path), filepath.Ext(path))
|
||||||
|
filenameCounts[filename]++
|
||||||
|
}
|
||||||
|
|
||||||
// Alright, let's convert each document to PDF.
|
// Alright, let's convert each document to PDF.
|
||||||
outputPaths := make([]string, len(inputPaths))
|
outputPaths := make([]string, len(inputPaths))
|
||||||
for i, inputPath := range inputPaths {
|
for i, inputPath := range inputPaths {
|
||||||
outputPaths[i] = ctx.GeneratePath(".pdf")
|
filename := strings.TrimSuffix(filepath.Base(inputPath), filepath.Ext(inputPath))
|
||||||
|
extension := filepath.Ext(inputPath)
|
||||||
|
// Ex: `document.docx`, `document.doc` -> `document.docx.pdf`, `document.doc.pdf`
|
||||||
|
if filenameCounts[filename] > 1 {
|
||||||
|
outputPaths[i] = ctx.GeneratePath(".pdf", filename+extension)
|
||||||
|
} else {
|
||||||
|
outputPaths[i] = ctx.GeneratePath(".pdf", filename)
|
||||||
|
}
|
||||||
|
|
||||||
options := libreofficeapi.Options{
|
options := libreofficeapi.Options{
|
||||||
Landscape: landscape,
|
Landscape: landscape,
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
@@ -22,6 +23,7 @@ func TestConvertRoute(t *testing.T) {
|
|||||||
engine gotenberg.PdfEngine
|
engine gotenberg.PdfEngine
|
||||||
expectOptions libreofficeapi.Options
|
expectOptions libreofficeapi.Options
|
||||||
expectError bool
|
expectError bool
|
||||||
|
expectFileNames []string
|
||||||
expectHttpError bool
|
expectHttpError bool
|
||||||
expectHttpStatus int
|
expectHttpStatus int
|
||||||
expectOutputPathsCount int
|
expectOutputPathsCount int
|
||||||
@@ -492,6 +494,72 @@ func TestConvertRoute(t *testing.T) {
|
|||||||
expectHttpError: false,
|
expectHttpError: false,
|
||||||
expectOutputPathsCount: 1,
|
expectOutputPathsCount: 1,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
scenario: "success (not merged, unique filenames with different extensions)",
|
||||||
|
ctx: func() *api.ContextMock {
|
||||||
|
ctx := &api.ContextMock{Context: new(api.Context)}
|
||||||
|
ctx.SetFiles(map[string]string{
|
||||||
|
"document.docx": "/document.docx",
|
||||||
|
"document2.docx": "/document2.docx",
|
||||||
|
})
|
||||||
|
ctx.SetValues(map[string][]string{
|
||||||
|
"merge": {
|
||||||
|
"false",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return ctx
|
||||||
|
}(),
|
||||||
|
libreOffice: &libreofficeapi.ApiMock{
|
||||||
|
PdfMock: func(ctx context.Context, logger *zap.Logger, inputPath, outputPath string, options libreofficeapi.Options) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
ExtensionsMock: func() []string {
|
||||||
|
return []string{".docx", ".doc"}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
engine: &gotenberg.PdfEngineMock{
|
||||||
|
MergeMock: func(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectError: false,
|
||||||
|
expectHttpError: false,
|
||||||
|
expectOutputPathsCount: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scenario: "success (not merged, duplicate filenames with different extensions)",
|
||||||
|
ctx: func() *api.ContextMock {
|
||||||
|
ctx := &api.ContextMock{Context: new(api.Context)}
|
||||||
|
ctx.SetFiles(map[string]string{
|
||||||
|
"document.docx": "/document.docx",
|
||||||
|
"document2.docx": "/document2.docx",
|
||||||
|
"document2.doc": "/document2.doc",
|
||||||
|
})
|
||||||
|
ctx.SetValues(map[string][]string{
|
||||||
|
"merge": {
|
||||||
|
"false",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return ctx
|
||||||
|
}(),
|
||||||
|
libreOffice: &libreofficeapi.ApiMock{
|
||||||
|
PdfMock: func(ctx context.Context, logger *zap.Logger, inputPath, outputPath string, options libreofficeapi.Options) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
ExtensionsMock: func() []string {
|
||||||
|
return []string{".docx", ".doc"}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
engine: &gotenberg.PdfEngineMock{
|
||||||
|
MergeMock: func(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectError: false,
|
||||||
|
expectHttpError: false,
|
||||||
|
expectOutputPathsCount: 3,
|
||||||
|
expectFileNames: []string{"document.pdf", "document2.docx.pdf", "document2.doc.pdf"},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
scenario: "success with non-native PDF/A & PDF/UA (merge)",
|
scenario: "success with non-native PDF/A & PDF/UA (merge)",
|
||||||
ctx: func() *api.ContextMock {
|
ctx: func() *api.ContextMock {
|
||||||
@@ -617,6 +685,10 @@ func TestConvertRoute(t *testing.T) {
|
|||||||
if tc.expectOutputPathsCount != len(tc.ctx.OutputPaths()) {
|
if tc.expectOutputPathsCount != len(tc.ctx.OutputPaths()) {
|
||||||
t.Errorf("expected %d output paths but got %d", tc.expectOutputPathsCount, len(tc.ctx.OutputPaths()))
|
t.Errorf("expected %d output paths but got %d", tc.expectOutputPathsCount, len(tc.ctx.OutputPaths()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(tc.ctx.OutputPaths(), tc.expectFileNames) {
|
||||||
|
t.Errorf("expected output paths %v, got %v", tc.expectFileNames, tc.ctx.OutputPaths())
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user