feat: file_save_disk, file_delete, file_serve, upload_parse, upload_handler, thumbnail_generate (issue 0014 fase 3)
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
package infra
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"mime"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// FileSaveDisk escribe el contenido de data en baseDir con un nombre unico generado a
|
||||
// partir de filename original. Crea baseDir si no existe.
|
||||
//
|
||||
// Retorna el UploadedFile con la metadata y la ruta completa en disco. El campo
|
||||
// ContentType se infiere de la extension via mime.TypeByExtension; si la app necesita
|
||||
// validacion mas estricta, debe usar FileValidateType antes y/o sobreescribir el campo.
|
||||
func FileSaveDisk(baseDir string, filename string, data io.Reader) (UploadedFile, error) {
|
||||
if err := os.MkdirAll(baseDir, 0o755); err != nil {
|
||||
return UploadedFile{}, fmt.Errorf("file_save_disk: mkdir %s: %w", baseDir, err)
|
||||
}
|
||||
|
||||
stored := FileUniqueName(filename)
|
||||
dst := filepath.Join(baseDir, stored)
|
||||
|
||||
f, err := os.Create(dst)
|
||||
if err != nil {
|
||||
return UploadedFile{}, fmt.Errorf("file_save_disk: create %s: %w", dst, err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
n, err := io.Copy(f, data)
|
||||
if err != nil {
|
||||
_ = os.Remove(dst)
|
||||
return UploadedFile{}, fmt.Errorf("file_save_disk: copy: %w", err)
|
||||
}
|
||||
|
||||
ext := strings.ToLower(filepath.Ext(stored))
|
||||
ct := mime.TypeByExtension(ext)
|
||||
if ct == "" {
|
||||
ct = "application/octet-stream"
|
||||
}
|
||||
|
||||
return UploadedFile{
|
||||
Filename: filename,
|
||||
StoredName: stored,
|
||||
Size: n,
|
||||
ContentType: ct,
|
||||
Path: dst,
|
||||
CreatedAt: time.Now().UTC(),
|
||||
}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user