El sistema que consume /v2/vcard/qr-url solo recibía "Error subiendo archivo a OSS": el motivo quedaba en nuestro log y del otro lado no había nada que hacer con eso. Ahora la respuesta incluye el error real del proveedor —es una API entre servidores y el que llama ya conoce la config de OSS que mandó— y el log dice además qué clave se intentó subir. La clave del objeto se armaba con el nombre tal como venía en el body. Un nombre con "/" o con caracteres que OSS no acepta producía justamente ese error genérico. Ahora se limpia. El mismo nombre crudo se usaba para el archivo temporal (/tmp/<nombre>.webp), o sea escritura de archivos en una ruta que elegía quien llamaba. Se fue entero: los tres endpoints suben desde memoria con UploadFromReader, que además saca el paso a disco y su limpieza. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
99 lines
2.8 KiB
Go
Executable File
99 lines
2.8 KiB
Go
Executable File
package controllers
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"log"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
"github.com/sujit-baniya/fiber-boilerplate/app"
|
|
"github.com/sujit-baniya/fiber-boilerplate/pkg/helpers"
|
|
"github.com/sujit-baniya/fiber-boilerplate/pkg/models"
|
|
"github.com/sujit-baniya/fiber-boilerplate/pkg/services"
|
|
"gorm.io/gorm"
|
|
// Importa el repositorio
|
|
)
|
|
|
|
func CreateVcf(c *fiber.Ctx) error {
|
|
var data services.ContactDataVcf
|
|
if err := json.Unmarshal(c.Body(), &data); err != nil {
|
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
|
"error": "Datos inválidos",
|
|
})
|
|
}
|
|
|
|
// 1. Generar el Vcf
|
|
vcfContent, err := services.GenerateVCardVcf(data)
|
|
if err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
|
"error": "No se pudo generar el VCF",
|
|
})
|
|
}
|
|
|
|
random := helpers.RandomString(4)
|
|
fileName := fmt.Sprintf("vcf/vcf-%s-%s.vcf", claveObjetoSegura(data.FirstName), random)
|
|
|
|
// 2. Subir a OSS directo desde memoria (ver el comentario en CreateQr).
|
|
ossProvider, err := getOSSFromBody(c)
|
|
if err != nil {
|
|
log.Printf("[VCF] No se pudo resolver la config de OSS: %v", err)
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
|
"error": "Error de conexión con OSS", "detalle": err.Error(),
|
|
})
|
|
}
|
|
|
|
if err := ossProvider.UploadFromReader(fileName, "text/vcard; charset=utf-8", bytes.NewReader(vcfContent)); err != nil {
|
|
log.Printf("Error subiendo archivo a OSS (%s): %v", fileName, err)
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
|
"error": "Error subiendo archivo a OSS", "detalle": err.Error(),
|
|
})
|
|
}
|
|
|
|
// 4. URL del archivo
|
|
url := ossProvider.PublicURL(fileName)
|
|
|
|
// 5. Buscar si ya existe un registro con ese vcard_id
|
|
var existing models.VcfVcard
|
|
db := app.Http.Database.DB
|
|
|
|
err = db.Where("vcard_id = ?", data.VcardID).First(&existing).Error
|
|
if err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
// No existe, crear nuevo
|
|
newVcf := models.VcfVcard{
|
|
Vcf: url,
|
|
UsuarioID: data.FirstName, // Podrías usar el ID real de usuario si lo tienes
|
|
Email: data.Email,
|
|
VcardID: data.VcardID,
|
|
}
|
|
if err := models.CreateVcfVcard(&newVcf); err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
|
"error": "No se pudo crear el registro VCF",
|
|
})
|
|
}
|
|
} else {
|
|
// Error inesperado de DB
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
|
"error": "Error buscando VCF existente",
|
|
})
|
|
}
|
|
} else {
|
|
// Si ya existe, actualizar
|
|
existing.Vcf = url
|
|
existing.Email = data.Email
|
|
existing.UsuarioID = data.FirstName
|
|
if err := models.UpdateVcfVcard(&existing); err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
|
"error": "No se pudo actualizar el VCF existente",
|
|
})
|
|
}
|
|
}
|
|
|
|
return c.JSON(fiber.Map{
|
|
"success": true,
|
|
"url": url,
|
|
})
|
|
}
|