v2.6.51: fix PDF import — raise UI body limit, wire real analyze
- docker-compose.yml: BODY_SIZE_LIMIT=52428800 (50MB) on UI service — adapter-node was rejecting PDFs >512KB with 'Content-length exceeds limit' - storage/import.go: add AnalyzeFile() public function using real PDF/EPUB parsers - handlers_import.go: analyzeImportFile() now calls storage.AnalyzeFile() instead of the file-size stub, so chapter count is accurate in the preview
This commit is contained in:
@@ -127,16 +127,17 @@ func (s *Server) handleAdminImport(w http.ResponseWriter, r *http.Request) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// analyzeImportFile does a quick scan of the file to count chapters.
|
// analyzeImportFile parses the file to count chapters and extract preview lines.
|
||||||
// This is a placeholder - real implementation would parse PDF/EPUB properly.
|
|
||||||
func analyzeImportFile(data []byte, fileType string) *importPreview {
|
func analyzeImportFile(data []byte, fileType string) *importPreview {
|
||||||
// TODO: Implement actual PDF/EPUB parsing to count chapters
|
count, firstLines, err := storage.AnalyzeFile(data, fileType)
|
||||||
// For now, estimate based on file size
|
if err != nil || count == 0 {
|
||||||
preview := &importPreview{
|
// Fall back to rough size estimate so the UI still shows something
|
||||||
Chapters: estimateChapters(data, fileType),
|
count = estimateChapters(data, fileType)
|
||||||
FirstLines: []string{},
|
}
|
||||||
|
return &importPreview{
|
||||||
|
Chapters: count,
|
||||||
|
FirstLines: firstLines,
|
||||||
}
|
}
|
||||||
return preview
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func estimateChapters(data []byte, fileType string) int {
|
func estimateChapters(data []byte, fileType string) int {
|
||||||
|
|||||||
@@ -54,7 +54,41 @@ func (i *importer) Import(ctx context.Context, objectKey, fileType string) ([]bo
|
|||||||
return parseEPUB(data)
|
return parseEPUB(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── PDF parsing ───────────────────────────────────────────────────────────────
|
// AnalyzeFile parses the given PDF or EPUB data and returns the detected
|
||||||
|
// chapter count and up to 3 preview lines (first non-empty line of each of
|
||||||
|
// the first 3 chapters). It is used by the analyze-only endpoint so users
|
||||||
|
// can preview chapter count before committing the import.
|
||||||
|
func AnalyzeFile(data []byte, fileType string) (chapterCount int, firstLines []string, err error) {
|
||||||
|
var chapters []bookstore.Chapter
|
||||||
|
switch fileType {
|
||||||
|
case "pdf":
|
||||||
|
chapters, err = parsePDF(data)
|
||||||
|
case "epub":
|
||||||
|
chapters, err = parseEPUB(data)
|
||||||
|
default:
|
||||||
|
return 0, nil, fmt.Errorf("unsupported file type: %s", fileType)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
chapterCount = len(chapters)
|
||||||
|
for i, ch := range chapters {
|
||||||
|
if i >= 3 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
line := strings.TrimSpace(ch.Content)
|
||||||
|
if nl := strings.Index(line, "\n"); nl > 0 {
|
||||||
|
line = line[:nl]
|
||||||
|
}
|
||||||
|
if len(line) > 120 {
|
||||||
|
line = line[:120] + "…"
|
||||||
|
}
|
||||||
|
firstLines = append(firstLines, line)
|
||||||
|
}
|
||||||
|
return chapterCount, firstLines, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func parsePDF(data []byte) ([]bookstore.Chapter, error) {
|
func parsePDF(data []byte) ([]bookstore.Chapter, error) {
|
||||||
r, err := pdf.NewReader(bytes.NewReader(data), int64(len(data)))
|
r, err := pdf.NewReader(bytes.NewReader(data), int64(len(data)))
|
||||||
|
|||||||
@@ -307,6 +307,8 @@ services:
|
|||||||
# OpenTelemetry tracing
|
# OpenTelemetry tracing
|
||||||
OTEL_EXPORTER_OTLP_ENDPOINT: "${OTEL_EXPORTER_OTLP_ENDPOINT}"
|
OTEL_EXPORTER_OTLP_ENDPOINT: "${OTEL_EXPORTER_OTLP_ENDPOINT}"
|
||||||
OTEL_SERVICE_NAME: "ui"
|
OTEL_SERVICE_NAME: "ui"
|
||||||
|
# Allow large PDF/EPUB uploads (adapter-node default is 512KB)
|
||||||
|
BODY_SIZE_LIMIT: "52428800"
|
||||||
# OAuth2 providers
|
# OAuth2 providers
|
||||||
GOOGLE_CLIENT_ID: "${GOOGLE_CLIENT_ID}"
|
GOOGLE_CLIENT_ID: "${GOOGLE_CLIENT_ID}"
|
||||||
GOOGLE_CLIENT_SECRET: "${GOOGLE_CLIENT_SECRET}"
|
GOOGLE_CLIENT_SECRET: "${GOOGLE_CLIENT_SECRET}"
|
||||||
|
|||||||
Reference in New Issue
Block a user