Skip to content

Instantly share code, notes, and snippets.

@SerJaimeLannister
Created September 28, 2025 18:23
Show Gist options
  • Select an option

  • Save SerJaimeLannister/d925689d54fe7ccf795d4c4ac1ed0b4a to your computer and use it in GitHub Desktop.

Select an option

Save SerJaimeLannister/d925689d54fe7ccf795d4c4ac1ed0b4a to your computer and use it in GitHub Desktop.
just for hackernews lol, license is unlicense but you have to buy me some soft drink if we meet and you used it (no obligation lol)
package main
import (
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"github.com/pdfcpu/pdfcpu/pkg/api"
)
func uploadForm(w http.ResponseWriter, r *http.Request) {
html := `
<!DOCTYPE html>
<html>
<head><title>Merge PDFs</title></head>
<body>
<h2>Upload PDFs to Merge</h2>
<form enctype="multipart/form-data" action="/merge" method="post">
<input type="file" name="files" multiple accept="application/pdf"/>
<input type="submit" value="Merge"/>
</form>
</body>
</html>
`
w.Header().Set("Content-Type", "text/html")
fmt.Fprint(w, html)
}
func mergeHandler(w http.ResponseWriter, r *http.Request) {
err := r.ParseMultipartForm(32 << 20) // 32 MB
if err != nil {
http.Error(w, "Failed to parse form", http.StatusBadRequest)
return
}
files := r.MultipartForm.File["files"]
if len(files) < 2 {
http.Error(w, "Upload at least 2 PDF files", http.StatusBadRequest)
return
}
var inputFiles []string
for _, fh := range files {
f, err := fh.Open()
if err != nil {
http.Error(w, "Failed to open uploaded file", http.StatusInternalServerError)
return
}
defer f.Close()
tmpPath := filepath.Join(os.TempDir(), fh.Filename)
out, err := os.Create(tmpPath)
if err != nil {
http.Error(w, "Failed to save file", http.StatusInternalServerError)
return
}
_, err = io.Copy(out, f)
out.Close()
if err != nil {
http.Error(w, "Failed to save file", http.StatusInternalServerError)
return
}
inputFiles = append(inputFiles, tmpPath)
}
mergedPath := filepath.Join(os.TempDir(), "merged.pdf")
// Updated pdfcpu call
err = api.MergeCreateFile(inputFiles, mergedPath, false, nil)
if err != nil {
http.Error(w, "Failed to merge PDFs: "+err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/pdf")
w.Header().Set("Content-Disposition", "attachment; filename=merged.pdf")
mergedFile, err := os.Open(mergedPath)
if err != nil {
http.Error(w, "Failed to open merged PDF", http.StatusInternalServerError)
return
}
defer mergedFile.Close()
io.Copy(w, mergedFile)
}
func main() {
http.HandleFunc("/", uploadForm)
http.HandleFunc("/merge", mergeHandler)
localIP := "0.0.0.0" // bind to all interfaces
port := "8080"
fmt.Printf("Server running at http://%s:%s\n", localIP, port)
err := http.ListenAndServe(localIP+":"+port, nil)
if err != nil {
fmt.Println("Failed to start server:", err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment