2eff52877b
retrieve document by id and tests * working * missing files
78 lines
2.1 KiB
Go
78 lines
2.1 KiB
Go
package documentdownload
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"mime"
|
|
"path/filepath"
|
|
|
|
"github.com/aws/aws-sdk-go-v2/service/s3"
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
// DownloadResult contains the data needed to stream a document file to the client.
|
|
type DownloadResult struct {
|
|
Body io.ReadCloser // S3 object body - caller must close
|
|
Filename string // Original filename (for Content-Disposition)
|
|
ContentType string // MIME type detected from filename extension
|
|
Size int64 // File size in bytes (for Content-Length)
|
|
}
|
|
|
|
// GetDownload retrieves the document file bytes from S3.
|
|
// Returns a DownloadResult with a streaming body that the caller must close.
|
|
func (s *Service) GetDownload(ctx context.Context, id uuid.UUID) (*DownloadResult, error) {
|
|
// Get document metadata (filename) from DB
|
|
doc, err := s.cfg.GetDBQueries().GetDocumentEnriched(ctx, id)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("document not found: %w", err)
|
|
}
|
|
|
|
// Get S3 entry (bucket, key) from documentEntries
|
|
entry, err := s.cfg.GetDBQueries().GetDocumentEntry(ctx, id)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("no S3 entry for document: %w", err)
|
|
}
|
|
|
|
// GetObject from S3
|
|
output, err := s.cfg.GetStoreClient().GetObject(ctx, &s3.GetObjectInput{
|
|
Bucket: &entry.Bucket,
|
|
Key: &entry.Key,
|
|
})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to retrieve file from S3: %w", err)
|
|
}
|
|
|
|
// Detect MIME type from filename extension
|
|
filename := ""
|
|
if doc.Filename != nil {
|
|
filename = *doc.Filename
|
|
}
|
|
contentType := detectContentType(filename)
|
|
|
|
// Get file size
|
|
var size int64
|
|
if output.ContentLength != nil {
|
|
size = *output.ContentLength
|
|
}
|
|
|
|
return &DownloadResult{
|
|
Body: output.Body,
|
|
Filename: filename,
|
|
ContentType: contentType,
|
|
Size: size,
|
|
}, nil
|
|
}
|
|
|
|
// detectContentType determines the MIME type based on file extension.
|
|
func detectContentType(filename string) string {
|
|
if filename == "" {
|
|
return "application/octet-stream"
|
|
}
|
|
contentType := mime.TypeByExtension(filepath.Ext(filename))
|
|
if contentType == "" {
|
|
return "application/octet-stream"
|
|
}
|
|
return contentType
|
|
}
|