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 }