diff --git a/pkg/modules/api/context.go b/pkg/modules/api/context.go index 43d298e..b5336d3 100644 --- a/pkg/modules/api/context.go +++ b/pkg/modules/api/context.go @@ -43,12 +43,13 @@ var ( // Context is the request context for a "multipart/form-data" request. type Context struct { - dirPath string - values map[string][]string - files map[string]string - filesByField map[string][]string - outputPaths []string - cancelled bool + dirPath string + values map[string][]string + files map[string]string + filesByField map[string][]string + diskToOriginal map[string]string + outputPaths []string + cancelled bool logger *slog.Logger echoCtx echo.Context @@ -200,6 +201,7 @@ func newContext(echoCtx echo.Context, logger *slog.Logger, fs *gotenberg.FileSys ctx.values = form.Value ctx.files = make(map[string]string) ctx.filesByField = make(map[string][]string) + ctx.diskToOriginal = make(map[string]string) // First, try to download files listed in the "downloadFrom" form field, if // any. @@ -348,7 +350,12 @@ func newContext(echoCtx echo.Context, logger *slog.Logger, fs *gotenberg.FileSys // normalized. // See: https://github.com/gotenberg/gotenberg/issues/662. filename = norm.NFC.String(filepath.Base(filename)) - path := fmt.Sprintf("%s/%s", ctx.dirPath, filename) + + // Use a UUID-based name on disk to avoid filesystem + // NAME_MAX limits with long filenames. + // See: https://github.com/gotenberg/gotenberg/issues/1500. + safeName := uuid.New().String() + filepath.Ext(filename) + path := fmt.Sprintf("%s/%s", ctx.dirPath, safeName) out, err := os.Create(path) if err != nil { @@ -381,6 +388,7 @@ func newContext(echoCtx echo.Context, logger *slog.Logger, fs *gotenberg.FileSys dlSpan.End() ctx.files[filename] = path + ctx.diskToOriginal[path] = filename // Route the downloaded file to the appropriate field bucket. switch { @@ -422,7 +430,12 @@ func newContext(echoCtx echo.Context, logger *slog.Logger, fs *gotenberg.FileSys // normalized. // See: https://github.com/gotenberg/gotenberg/issues/662. filename := norm.NFC.String(filepath.Base(fh.Filename)) - path := fmt.Sprintf("%s/%s", ctx.dirPath, filename) + + // Use a UUID-based name on disk to avoid filesystem + // NAME_MAX limits with long filenames. + // See: https://github.com/gotenberg/gotenberg/issues/1500. + safeName := uuid.New().String() + filepath.Ext(filename) + path := fmt.Sprintf("%s/%s", ctx.dirPath, safeName) out, err := os.Create(path) if err != nil { @@ -441,6 +454,7 @@ func newContext(echoCtx echo.Context, logger *slog.Logger, fs *gotenberg.FileSys } ctx.files[filename] = path + ctx.diskToOriginal[path] = filename return nil } @@ -475,13 +489,29 @@ func (ctx *Context) Request() *http.Request { // FormData return a [FormData]. func (ctx *Context) FormData() *FormData { return &FormData{ - values: ctx.values, - files: ctx.files, - filesByField: ctx.filesByField, - errors: nil, + values: ctx.values, + files: ctx.files, + filesByField: ctx.filesByField, + diskToOriginal: ctx.diskToOriginal, + errors: nil, } } +// OriginalFilename returns the original filename associated with a disk path. +// If no mapping exists, it falls back to [filepath.Base]. +func (ctx *Context) OriginalFilename(diskPath string) string { + if original, ok := ctx.diskToOriginal[diskPath]; ok { + return original + } + return filepath.Base(diskPath) +} + +// RegisterDiskPath associates a disk path with an original filename so that +// [Context.OriginalFilename] can resolve it later. +func (ctx *Context) RegisterDiskPath(diskPath, originalFilename string) { + ctx.diskToOriginal[diskPath] = originalFilename +} + // DirPath returns the path to the request's working directory. func (ctx *Context) DirPath() string { return ctx.dirPath @@ -494,10 +524,14 @@ func (ctx *Context) GeneratePath(extension string) string { } // GeneratePathFromFilename generates a path within the context's working -// directory, using the given filename (with extension). It does not create -// a file. +// directory. It uses a UUID-based name on disk to avoid filesystem NAME_MAX +// limits but registers the given filename so that [Context.OriginalFilename] +// can resolve it. It does not create a file. func (ctx *Context) GeneratePathFromFilename(filename string) string { - return fmt.Sprintf("%s/%s", ctx.dirPath, filename) + safeName := uuid.New().String() + filepath.Ext(filename) + path := fmt.Sprintf("%s/%s", ctx.dirPath, safeName) + ctx.diskToOriginal[path] = filename + return path } // CreateSubDirectory creates a subdirectory within the context's working @@ -564,7 +598,7 @@ func (ctx *Context) BuildOutputFile() (string, error) { filesInfo, err := archives.FilesFromDisk(ctx.Context, nil, func() map[string]string { f := make(map[string]string) for _, outputPath := range ctx.outputPaths { - f[outputPath] = "" + f[outputPath] = ctx.OriginalFilename(outputPath) } return f }()) @@ -600,7 +634,7 @@ func (ctx *Context) OutputFilename(outputPath string) string { filename := ctx.echoCtx.Get("outputFilename").(string) if filename == "" { - return filepath.Base(outputPath) + return ctx.OriginalFilename(outputPath) } return fmt.Sprintf("%s%s", filename, filepath.Ext(outputPath)) diff --git a/pkg/modules/api/formdata.go b/pkg/modules/api/formdata.go index f2eca94..007ecc1 100644 --- a/pkg/modules/api/formdata.go +++ b/pkg/modules/api/formdata.go @@ -33,10 +33,11 @@ const ( // // form := ctx.FormData() type FormData struct { - values map[string][]string - files map[string]string - filesByField map[string][]string - errors error + values map[string][]string + files map[string]string + filesByField map[string][]string + diskToOriginal map[string]string + errors error } // Validate returns nil or an error related to the [FormData] values, with a @@ -450,6 +451,15 @@ func (form *FormData) paths(extensions []string, target *[]string) *FormData { watermarks, wmOk := form.filesByField[WatermarkFormField] stamps, stOk := form.filesByField[StampFormField] + // Collect (originalFilename, diskPath) pairs so that we can sort by + // original filename rather than by UUID-based disk name. + // See https://github.com/gotenberg/gotenberg/issues/1500. + type entry struct { + original string + disk string + } + var entries []entry + for filename, path := range form.files { if ok && slices.Contains(embeds, path) { continue @@ -466,13 +476,26 @@ func (form *FormData) paths(extensions []string, target *[]string) *FormData { for _, ext := range extensions { // See https://github.com/gotenberg/gotenberg/issues/228. if strings.ToLower(filepath.Ext(filename)) == ext { - *target = append(*target, path) + entries = append(entries, entry{original: filename, disk: path}) } } } // See https://github.com/gotenberg/gotenberg/issues/139. - sort.Sort(gotenberg.AlphanumericSort(*target)) + originals := make(gotenberg.AlphanumericSort, len(entries)) + for i, e := range entries { + originals[i] = e.original + } + sort.Sort(originals) + + // Build a lookup from original name to disk path. + lookup := make(map[string]string, len(entries)) + for _, e := range entries { + lookup[e.original] = e.disk + } + for _, o := range originals { + *target = append(*target, lookup[o]) + } return form } diff --git a/pkg/modules/chromium/routes.go b/pkg/modules/chromium/routes.go index fa866ab..995091d 100644 --- a/pkg/modules/chromium/routes.go +++ b/pkg/modules/chromium/routes.go @@ -667,7 +667,7 @@ func markdownToHtml(ctx *api.Context, inputPath string, markdownPaths []string) var path string for _, markdownPath := range markdownPaths { - markdownFilename := filepath.Base(markdownPath) + markdownFilename := ctx.OriginalFilename(markdownPath) if filename == markdownFilename { path = markdownPath diff --git a/pkg/modules/libreoffice/routes.go b/pkg/modules/libreoffice/routes.go index fcc0b33..f3e996c 100644 --- a/pkg/modules/libreoffice/routes.go +++ b/pkg/modules/libreoffice/routes.go @@ -420,7 +420,8 @@ func convertRoute(libreOffice libreofficeapi.Uno, engine gotenberg.PdfEngine) ap // document.docx -> document.docx.pdf, so that split naming // document.docx_0.pdf, etc. for i, inputPath := range inputPaths { - outputPath := fmt.Sprintf("%s.pdf", inputPath) + originalName := ctx.OriginalFilename(inputPath) + outputPath := ctx.GeneratePathFromFilename(originalName + ".pdf") err = ctx.Rename(outputPaths[i], outputPath) if err != nil { @@ -502,7 +503,8 @@ func convertRoute(libreOffice libreofficeapi.Uno, engine gotenberg.PdfEngine) ap if len(outputPaths) > 1 && splitMode == zeroValuedSplitMode { // If .zip archive, document.docx -> document.docx.pdf. for i, inputPath := range inputPaths { - outputPath := fmt.Sprintf("%s.pdf", inputPath) + originalName := ctx.OriginalFilename(inputPath) + outputPath := ctx.GeneratePathFromFilename(originalName + ".pdf") err = ctx.Rename(outputPaths[i], outputPath) if err != nil { diff --git a/pkg/modules/pdfengines/routes.go b/pkg/modules/pdfengines/routes.go index bdac91e..b1df965 100644 --- a/pkg/modules/pdfengines/routes.go +++ b/pkg/modules/pdfengines/routes.go @@ -5,10 +5,12 @@ import ( "errors" "fmt" "net/http" + "os" "path/filepath" "strconv" "strings" + "github.com/google/uuid" "github.com/labstack/echo/v4" "github.com/gotenberg/gotenberg/v8/pkg/gotenberg" @@ -282,9 +284,9 @@ func SplitPdfStub(ctx *api.Context, engine gotenberg.PdfEngine, mode gotenberg.S var outputPaths []string for _, inputPath := range inputPaths { - inputPathNoExt := inputPath[:len(inputPath)-len(filepath.Ext(inputPath))] - filenameNoExt := filepath.Base(inputPathNoExt) - outputDirPath, err := ctx.CreateSubDirectory(strings.ReplaceAll(filepath.Base(filenameNoExt), ".", "_")) + originalName := ctx.OriginalFilename(inputPath) + originalNameNoExt := strings.TrimSuffix(originalName, filepath.Ext(originalName)) + outputDirPath, err := ctx.CreateSubDirectory(uuid.New().String()) if err != nil { return nil, fmt.Errorf("create subdirectory from input path: %w", err) } @@ -297,15 +299,18 @@ func SplitPdfStub(ctx *api.Context, engine gotenberg.PdfEngine, mode gotenberg.S // Keep the original filename. for i, path := range paths { var newPath string + var newOriginal string if mode.Unify && mode.Mode == gotenberg.SplitModePages { + newOriginal = fmt.Sprintf("%s.pdf", originalNameNoExt) newPath = fmt.Sprintf( - "%s/%s.pdf", - outputDirPath, filenameNoExt, + "%s/%s", + outputDirPath, uuid.New().String()+".pdf", ) } else { + newOriginal = fmt.Sprintf("%s_%d.pdf", originalNameNoExt, i) newPath = fmt.Sprintf( - "%s/%s_%d.pdf", - outputDirPath, filenameNoExt, i, + "%s/%s", + outputDirPath, uuid.New().String()+".pdf", ) } @@ -314,6 +319,7 @@ func SplitPdfStub(ctx *api.Context, engine gotenberg.PdfEngine, mode gotenberg.S return nil, fmt.Errorf("rename path: %w", err) } + ctx.RegisterDiskPath(newPath, newOriginal) outputPaths = append(outputPaths, newPath) if mode.Unify && mode.Mode == gotenberg.SplitModePages { @@ -413,7 +419,7 @@ func WriteBookmarksStub(ctx *api.Context, engine gotenberg.PdfEngine, bookmarks } case map[string][]gotenberg.Bookmark: for _, inputPath := range inputPaths { - filename := filepath.Base(inputPath) + filename := ctx.OriginalFilename(inputPath) if specificBookmarks, ok := b[filename]; ok { err := engine.WriteBookmarks(ctx, ctx.Log(), inputPath, specificBookmarks) if err != nil { @@ -466,8 +472,28 @@ func EmbedFilesStub(ctx *api.Context, engine gotenberg.PdfEngine, embedPaths []s return nil } + // Engines like pdfcpu use filepath.Base(path) as the attachment name + // inside the PDF. Since disk filenames are now UUID-based, we create + // symlinks with the original names so that embeds are named correctly. + // See: https://github.com/gotenberg/gotenberg/issues/1500. + embedDir, err := ctx.CreateSubDirectory(uuid.New().String()) + if err != nil { + return fmt.Errorf("create embed subdirectory: %w", err) + } + + resolvedPaths := make([]string, len(embedPaths)) + for i, embedPath := range embedPaths { + originalName := ctx.OriginalFilename(embedPath) + resolvedPath := fmt.Sprintf("%s/%s", embedDir, originalName) + err := os.Symlink(embedPath, resolvedPath) + if err != nil { + return fmt.Errorf("symlink embed file '%s': %w", originalName, err) + } + resolvedPaths[i] = resolvedPath + } + for _, inputPath := range inputPaths { - err := engine.EmbedFiles(ctx, ctx.Log(), embedPaths, inputPath) + err := engine.EmbedFiles(ctx, ctx.Log(), resolvedPaths, inputPath) if err != nil { return fmt.Errorf("embed files into PDF '%s': %w", inputPath, err) } @@ -683,7 +709,7 @@ func mergeRoute(engine gotenberg.PdfEngine) api.Route { if bMap != nil || autoIndexBookmarks { offset := 0 for _, inputPath := range inputPaths { - filename := filepath.Base(inputPath) + filename := ctx.OriginalFilename(inputPath) var fileBookmarks []gotenberg.Bookmark if bMap != nil { @@ -973,7 +999,7 @@ func readMetadataRoute(engine gotenberg.PdfEngine) api.Route { return fmt.Errorf("read metadata: %w", err) } - res[filepath.Base(inputPath)] = metadata + res[ctx.OriginalFilename(inputPath)] = metadata } err = c.JSON(http.StatusOK, res) @@ -1051,7 +1077,7 @@ func readBookmarksRoute(engine gotenberg.PdfEngine) api.Route { return fmt.Errorf("read bookmarks: %w", err) } - res[filepath.Base(inputPath)] = bookmarks + res[ctx.OriginalFilename(inputPath)] = bookmarks } err = c.JSON(http.StatusOK, res) diff --git a/test/integration/features/chromium_convert_html.feature b/test/integration/features/chromium_convert_html.feature index 516d8a7..6d32c49 100644 --- a/test/integration/features/chromium_convert_html.feature +++ b/test/integration/features/chromium_convert_html.feature @@ -1152,3 +1152,14 @@ Feature: /forms/chromium/convert/html | files | testdata/page-1-html/index.html | file | Then the response status code should be 200 Then the response header "Content-Type" should be "application/pdf" + + # See: https://github.com/gotenberg/gotenberg/issues/1500. + Scenario: POST /forms/chromium/convert/html (Long Filename) + Given I have a default Gotenberg container + When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s): + | files | testdata/page-1-html/index.html | file | + | Gotenberg-Output-Filename | foo | header | + Then the response status code should be 200 + Then the response header "Content-Type" should be "application/pdf" + Then there should be 1 PDF(s) in the response + Then the "foo.pdf" PDF should have 1 page(s) diff --git a/test/integration/features/chromium_convert_markdown.feature b/test/integration/features/chromium_convert_markdown.feature index dfb3d11..170682c 100644 --- a/test/integration/features/chromium_convert_markdown.feature +++ b/test/integration/features/chromium_convert_markdown.feature @@ -1128,3 +1128,15 @@ Feature: /forms/chromium/convert/markdown | files | testdata/page-1-markdown/page_1.md | file | Then the response status code should be 200 Then the response header "Content-Type" should be "application/pdf" + + # See: https://github.com/gotenberg/gotenberg/issues/1500. + Scenario: POST /forms/chromium/convert/markdown (Long Filename) + Given I have a default Gotenberg container + When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/markdown" endpoint with the following form data and header(s): + | files | testdata/page-1-markdown/index.html | file | + | files | testdata/page-1-markdown/page_1.md | file | + | Gotenberg-Output-Filename | foo | header | + Then the response status code should be 200 + Then the response header "Content-Type" should be "application/pdf" + Then there should be 1 PDF(s) in the response + Then the "foo.pdf" PDF should have 1 page(s) diff --git a/test/integration/features/libreoffice_convert.feature b/test/integration/features/libreoffice_convert.feature index 60c478b..2a74613 100644 --- a/test/integration/features/libreoffice_convert.feature +++ b/test/integration/features/libreoffice_convert.feature @@ -781,3 +781,14 @@ Feature: /forms/libreoffice/convert | files | testdata/page_1.docx | file | Then the response status code should be 200 Then the response header "Content-Type" should be "application/pdf" + + # See: https://github.com/gotenberg/gotenberg/issues/1500. + Scenario: POST /forms/libreoffice/convert (Long Filename) + Given I have a default Gotenberg container + When I make a "POST" request to Gotenberg at the "/forms/libreoffice/convert" endpoint with the following form data and header(s): + | files | testdata/Longitudinell_jämförelse_mellan_laserkirurgi_och_strålbehandling_gällande_röstkvalitet_och_självskattad_kommunikation_upp_till_två_år_efter_tidig_stämbandscancer_i_ett_randomiserat_kontrollerat_försök.docx | file | + | Gotenberg-Output-Filename | foo | header | + Then the response status code should be 200 + Then the response header "Content-Type" should be "application/pdf" + Then there should be 1 PDF(s) in the response + Then the "foo.pdf" PDF should have 1 page(s) diff --git a/test/integration/features/pdfengines_encrypt.feature b/test/integration/features/pdfengines_encrypt.feature index c397054..62bc6a3 100644 --- a/test/integration/features/pdfengines_encrypt.feature +++ b/test/integration/features/pdfengines_encrypt.feature @@ -180,3 +180,15 @@ Feature: /forms/pdfengines/encrypt | userPassword | foo | field | Then the response status code should be 200 Then the response header "Content-Type" should be "application/pdf" + + # See: https://github.com/gotenberg/gotenberg/issues/1500. + Scenario: POST /forms/pdfengines/encrypt (Long Filename) + Given I have a default Gotenberg container + When I make a "POST" request to Gotenberg at the "/forms/pdfengines/encrypt" endpoint with the following form data and header(s): + | files | testdata/Longitudinell_jämförelse_mellan_laserkirurgi_och_strålbehandling_gällande_röstkvalitet_och_självskattad_kommunikation_upp_till_två_år_efter_tidig_stämbandscancer_i_ett_randomiserat_kontrollerat_försök.pdf | file | + | userPassword | foo | field | + | ownerPassword | bar | field | + | Gotenberg-Output-Filename | foo | header | + Then the response status code should be 200 + Then the response header "Content-Type" should be "application/pdf" + Then there should be 1 PDF(s) in the response diff --git a/test/integration/features/pdfengines_flatten.feature b/test/integration/features/pdfengines_flatten.feature index 10bff85..56f2b79 100644 --- a/test/integration/features/pdfengines_flatten.feature +++ b/test/integration/features/pdfengines_flatten.feature @@ -118,3 +118,14 @@ Feature: /forms/pdfengines/flatten | files | testdata/page_1.pdf | file | Then the response status code should be 200 Then the response header "Content-Type" should be "application/pdf" + + # See: https://github.com/gotenberg/gotenberg/issues/1500. + Scenario: POST /forms/pdfengines/flatten (Long Filename) + Given I have a default Gotenberg container + When I make a "POST" request to Gotenberg at the "/forms/pdfengines/flatten" endpoint with the following form data and header(s): + | files | testdata/Longitudinell_jämförelse_mellan_laserkirurgi_och_strålbehandling_gällande_röstkvalitet_och_självskattad_kommunikation_upp_till_två_år_efter_tidig_stämbandscancer_i_ett_randomiserat_kontrollerat_försök.pdf | file | + | Gotenberg-Output-Filename | foo | header | + Then the response status code should be 200 + Then the response header "Content-Type" should be "application/pdf" + Then there should be 1 PDF(s) in the response + Then the response PDF(s) should be flatten diff --git a/test/integration/features/pdfengines_merge.feature b/test/integration/features/pdfengines_merge.feature index f418591..5693046 100644 --- a/test/integration/features/pdfengines_merge.feature +++ b/test/integration/features/pdfengines_merge.feature @@ -664,3 +664,14 @@ Feature: /forms/pdfengines/merge | pdfa | PDF/A-3b | field | | embeds | testdata/embed_1.xml | file | Then the response status code should be 200 + + # See: https://github.com/gotenberg/gotenberg/issues/1500. + Scenario: POST /forms/pdfengines/merge (Long Filename) + Given I have a default Gotenberg container + When I make a "POST" request to Gotenberg at the "/forms/pdfengines/merge" endpoint with the following form data and header(s): + | files | testdata/Longitudinell_jämförelse_mellan_laserkirurgi_och_strålbehandling_gällande_röstkvalitet_och_självskattad_kommunikation_upp_till_två_år_efter_tidig_stämbandscancer_i_ett_randomiserat_kontrollerat_försök.pdf | file | + | files | testdata/page_2.pdf | file | + | Gotenberg-Output-Filename | foo | header | + Then the response status code should be 200 + Then the response header "Content-Type" should be "application/pdf" + Then there should be 1 PDF(s) in the response diff --git a/test/integration/features/pdfengines_metadata.feature b/test/integration/features/pdfengines_metadata.feature index de2a430..24ceb44 100644 --- a/test/integration/features/pdfengines_metadata.feature +++ b/test/integration/features/pdfengines_metadata.feature @@ -293,3 +293,21 @@ Feature: /forms/pdfengines/metadata/{write|read} | files | teststore/foo.pdf | file | Then the response status code should be 200 Then the response header "Content-Type" should be "application/json" + + # See: https://github.com/gotenberg/gotenberg/issues/1500. + Scenario: POST /forms/pdfengines/metadata/read (Long Filename) + Given I have a default Gotenberg container + When I make a "POST" request to Gotenberg at the "/forms/pdfengines/metadata/read" endpoint with the following form data and header(s): + | files | testdata/Longitudinell_jämförelse_mellan_laserkirurgi_och_strålbehandling_gällande_röstkvalitet_och_självskattad_kommunikation_upp_till_två_år_efter_tidig_stämbandscancer_i_ett_randomiserat_kontrollerat_försök.pdf | file | + Then the response status code should be 200 + + # See: https://github.com/gotenberg/gotenberg/issues/1500. + Scenario: POST /forms/pdfengines/metadata/write (Long Filename) + Given I have a default Gotenberg container + When I make a "POST" request to Gotenberg at the "/forms/pdfengines/metadata/write" endpoint with the following form data and header(s): + | files | testdata/Longitudinell_jämförelse_mellan_laserkirurgi_och_strålbehandling_gällande_röstkvalitet_och_självskattad_kommunikation_upp_till_två_år_efter_tidig_stämbandscancer_i_ett_randomiserat_kontrollerat_försök.pdf | file | + | metadata | {"Author":"Test"} | field | + | Gotenberg-Output-Filename | foo | header | + Then the response status code should be 200 + Then the response header "Content-Type" should be "application/pdf" + Then there should be 1 PDF(s) in the response diff --git a/test/integration/features/pdfengines_rotate.feature b/test/integration/features/pdfengines_rotate.feature index 358e19a..0400aad 100644 --- a/test/integration/features/pdfengines_rotate.feature +++ b/test/integration/features/pdfengines_rotate.feature @@ -162,3 +162,14 @@ Feature: /forms/pdfengines/rotate | rotateAngle | 90 | field | Then the response status code should be 200 Then the response header "Content-Type" should be "application/pdf" + + # See: https://github.com/gotenberg/gotenberg/issues/1500. + Scenario: POST /forms/pdfengines/rotate (Long Filename) + Given I have a default Gotenberg container + When I make a "POST" request to Gotenberg at the "/forms/pdfengines/rotate" endpoint with the following form data and header(s): + | files | testdata/Longitudinell_jämförelse_mellan_laserkirurgi_och_strålbehandling_gällande_röstkvalitet_och_självskattad_kommunikation_upp_till_två_år_efter_tidig_stämbandscancer_i_ett_randomiserat_kontrollerat_försök.pdf | file | + | rotateAngle | 90 | field | + | Gotenberg-Output-Filename | foo | header | + Then the response status code should be 200 + Then the response header "Content-Type" should be "application/pdf" + Then there should be 1 PDF(s) in the response diff --git a/test/integration/features/pdfengines_split.feature b/test/integration/features/pdfengines_split.feature index f9b1764..8796348 100644 --- a/test/integration/features/pdfengines_split.feature +++ b/test/integration/features/pdfengines_split.feature @@ -764,3 +764,16 @@ Feature: /forms/pdfengines/split | pdfa | PDF/A-3b | field | | embeds | testdata/embed_1.xml | file | Then the response status code should be 200 + + # See: https://github.com/gotenberg/gotenberg/issues/1500. + Scenario: POST /forms/pdfengines/split (Long Filename) + Given I have a default Gotenberg container + When I make a "POST" request to Gotenberg at the "/forms/pdfengines/split" endpoint with the following form data and header(s): + | files | testdata/Longitudinell_jämförelse_mellan_laserkirurgi_och_strålbehandling_gällande_röstkvalitet_och_självskattad_kommunikation_upp_till_två_år_efter_tidig_stämbandscancer_i_ett_randomiserat_kontrollerat_försök.pdf | file | + | splitMode | pages | field | + | splitSpan | 1 | field | + | splitUnify | true | field | + | Gotenberg-Output-Filename | foo | header | + Then the response status code should be 200 + Then the response header "Content-Type" should be "application/pdf" + Then there should be 1 PDF(s) in the response diff --git a/test/integration/testdata/Longitudinell_jämförelse_mellan_laserkirurgi_och_strålbehandling_gällande_röstkvalitet_och_självskattad_kommunikation_upp_till_två_år_efter_tidig_stämbandscancer_i_ett_randomiserat_kontrollerat_försök.docx b/test/integration/testdata/Longitudinell_jämförelse_mellan_laserkirurgi_och_strålbehandling_gällande_röstkvalitet_och_självskattad_kommunikation_upp_till_två_år_efter_tidig_stämbandscancer_i_ett_randomiserat_kontrollerat_försök.docx new file mode 100644 index 0000000..1868509 Binary files /dev/null and b/test/integration/testdata/Longitudinell_jämförelse_mellan_laserkirurgi_och_strålbehandling_gällande_röstkvalitet_och_självskattad_kommunikation_upp_till_två_år_efter_tidig_stämbandscancer_i_ett_randomiserat_kontrollerat_försök.docx differ diff --git a/test/integration/testdata/Longitudinell_jämförelse_mellan_laserkirurgi_och_strålbehandling_gällande_röstkvalitet_och_självskattad_kommunikation_upp_till_två_år_efter_tidig_stämbandscancer_i_ett_randomiserat_kontrollerat_försök.pdf b/test/integration/testdata/Longitudinell_jämförelse_mellan_laserkirurgi_och_strålbehandling_gällande_röstkvalitet_och_självskattad_kommunikation_upp_till_två_år_efter_tidig_stämbandscancer_i_ett_randomiserat_kontrollerat_försök.pdf new file mode 100644 index 0000000..c41ff06 Binary files /dev/null and b/test/integration/testdata/Longitudinell_jämförelse_mellan_laserkirurgi_och_strålbehandling_gällande_röstkvalitet_och_självskattad_kommunikation_upp_till_två_år_efter_tidig_stämbandscancer_i_ett_randomiserat_kontrollerat_försök.pdf differ