using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Localization; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Formats.Webp; using SixLabors.ImageSharp.Formats.Jpeg; namespace Convert_It_Online.Areas.ImageConverters.Controllers { [Area("ImageConverters")] public class JpgToWebpController : Controller { private readonly IStringLocalizer _localizer; private readonly ILogger _logger; public JpgToWebpController(IStringLocalizer localizer, ILogger logger) { _localizer = localizer; _logger = logger; } private void SetCommonViewBagProperties() { ViewBag.HomeLink = _localizer["HomeLink"]; ViewBag.TextMenuTitle = _localizer["TextMenuTitle"]; ViewBag.ImageMenuTitle = _localizer["ImageMenuTitle"]; ViewBag.CaseConverterTitle = _localizer["CaseConverterTitle"]; ViewBag.JpgToWebpTitle = _localizer["JpgToWebpTitle"]; ViewBag.HeicToJpgTitle = _localizer["HeicToJpgTitle"]; ViewBag.DocumentMenuTitle = _localizer["DocumentMenuTitle"]; ViewBag.PdfToTextTitle = _localizer["PdfToTextTitle"]; ViewBag.PdfBarcodeTitle = _localizer["PdfBarcodeTitle"]; ViewBag.FooterText = _localizer["FooterText"]; ViewBag.About = _localizer["About"]; ViewBag.Contact = _localizer["Contact"]; ViewBag.Terms = _localizer["Terms"]; } private void PrepareIndexView() { SetCommonViewBagProperties(); ViewBag.PageTitle = _localizer["JpgWebpConverterPageTitle"]; ViewBag.PageDescription = _localizer["JpgWebpConverterPageDescription"]; ViewBag.JpgToWebpTabTitle = _localizer["JpgToWebpTabTitle"]; ViewBag.WebpToJpgTabTitle = _localizer["WebpToJpgTabTitle"]; ViewBag.JpgFileInputLabel = _localizer["JpgFileInputLabel"]; ViewBag.WebpFileInputLabel = _localizer["WebpFileInputLabel"]; ViewBag.ConvertToWebpButton = _localizer["ConvertToWebpButton"]; ViewBag.ConvertToJpgButton = _localizer["ConvertToJpgButton"]; // FAQ properties ViewBag.FaqWhatTitle = _localizer["JpgWebpFaqWhatTitle"]; ViewBag.FaqWhatContent = _localizer["JpgWebpFaqWhatContent"]; ViewBag.FaqHowTitle = _localizer["JpgWebpFaqHowTitle"]; ViewBag.FaqHowContent = _localizer["JpgWebpFaqHowContent"]; ViewBag.FaqWhyTitle = _localizer["JpgWebpFaqWhyTitle"]; ViewBag.FaqWhyContent = _localizer["JpgWebpFaqWhyContent"]; ViewBag.FaqSecurityTitle = _localizer["JpgWebpFaqSecurityTitle"]; ViewBag.FaqSecurityContent = _localizer["JpgWebpFaqSecurityContent"]; ViewBag.FaqLimitsTitle = _localizer["JpgWebpFaqLimitsTitle"]; ViewBag.FaqLimitsContent = _localizer["JpgWebpFaqLimitsContent"]; ViewBag.MetaDescription = ViewBag.PageDescription; } public IActionResult Index() { PrepareIndexView(); return View(); } [HttpPost] public async Task ConvertJpgToWebp(IFormFile jpgFile, bool preview = false) { if (jpgFile == null || jpgFile.Length == 0) { _logger.LogWarning("[JPG-WEBP-CONVERTER] Tentativa de conversão sem arquivo"); if (preview) { return Json(new { success = false, message = _localizer["SelectFileError"].Value }); } ModelState.AddModelError("jpgFile", _localizer["SelectFileError"]); PrepareIndexView(); return View("Index"); } if (jpgFile.ContentType != "image/jpeg" && !jpgFile.FileName.ToLower().EndsWith(".jpg") && !jpgFile.FileName.ToLower().EndsWith(".jpeg")) { _logger.LogWarning("[JPG-WEBP-CONVERTER] Arquivo JPG inválido: {ContentType}", jpgFile.ContentType); if (preview) { return Json(new { success = false, message = _localizer["InvalidJpgFileError"].Value }); } ModelState.AddModelError("jpgFile", _localizer["InvalidJpgFileError"]); PrepareIndexView(); return View("Index"); } try { _logger.LogInformation("[JPG-WEBP-CONVERTER] Iniciando conversão JPG→WebP: {FileName} ({Size} bytes)", jpgFile.FileName, jpgFile.Length); var originalSize = jpgFile.Length; // Limite para preview: 10MB const long maxPreviewSize = 10 * 1024 * 1024; using var jpgStream = jpgFile.OpenReadStream(); using var image = await Image.LoadAsync(jpgStream); using var memoryStream = new MemoryStream(); await image.SaveAsWebpAsync(memoryStream); var webpData = memoryStream.ToArray(); var convertedSize = webpData.Length; var fileName = Path.GetFileNameWithoutExtension(jpgFile.FileName) + ".webp"; _logger.LogInformation("[JPG-WEBP-CONVERTER] Conversão JPG→WebP concluída: {OutputFileName} (Original: {OriginalSize}bytes → Convertido: {ConvertedSize}bytes)", fileName, originalSize, convertedSize); // Se é request de preview e o arquivo não é muito grande if (preview && originalSize <= maxPreviewSize && convertedSize <= maxPreviewSize) { var base64 = Convert.ToBase64String(webpData); var base64DataUrl = $"data:image/webp;base64,{base64}"; return Json(new { success = true, base64 = base64DataUrl, filename = fileName, originalSize = originalSize, convertedSize = convertedSize }); } // Download normal return File(webpData, "image/webp", fileName); } catch (UnknownImageFormatException) { _logger.LogWarning("[JPG-WEBP-CONVERTER] O arquivo JPG parece ser inválido ou o formato não é suportado."); if (preview) { return Json(new { success = false, message = _localizer["InvalidJpgFileError"].Value }); } ModelState.AddModelError("jpgFile", _localizer["InvalidJpgFileError"]); ViewBag.ConversionError = _localizer["InvalidJpgFileError"]; PrepareIndexView(); return View("Index"); } catch (Exception ex) { _logger.LogError(ex, "[JPG-WEBP-CONVERTER] Erro ao converter JPG para WebP: {FileName}", jpgFile.FileName); if (preview) { return Json(new { success = false, message = _localizer["ProcessingError"].Value }); } ModelState.AddModelError("jpgFile", _localizer["ProcessingError"]); ViewBag.ConversionError = _localizer["ProcessingError"]; PrepareIndexView(); return View("Index"); } } [HttpPost] public async Task ConvertWebpToJpg(IFormFile webpFile, bool preview = false) { if (webpFile == null || webpFile.Length == 0) { _logger.LogWarning("[JPG-WEBP-CONVERTER] Tentativa de conversão WebP→JPG sem arquivo"); if (preview) { return Json(new { success = false, message = _localizer["SelectFileError"].Value }); } ModelState.AddModelError("webpFile", _localizer["SelectFileError"]); PrepareIndexView(); return View("Index"); } if (webpFile.ContentType != "image/webp" && !webpFile.FileName.ToLower().EndsWith(".webp")) { _logger.LogWarning("[JPG-WEBP-CONVERTER] Arquivo WebP inválido: {ContentType}", webpFile.ContentType); if (preview) { return Json(new { success = false, message = "Arquivo WebP inválido ou formato não suportado." }); } ModelState.AddModelError("webpFile", "Arquivo WebP inválido ou formato não suportado."); PrepareIndexView(); return View("Index"); } try { _logger.LogInformation("[JPG-WEBP-CONVERTER] Iniciando conversão WebP→JPG: {FileName} ({Size} bytes)", webpFile.FileName, webpFile.Length); var originalSize = webpFile.Length; // Limite para preview: 10MB const long maxPreviewSize = 10 * 1024 * 1024; using var webpStream = webpFile.OpenReadStream(); using var image = await Image.LoadAsync(webpStream); using var memoryStream = new MemoryStream(); await image.SaveAsJpegAsync(memoryStream); var jpgData = memoryStream.ToArray(); var convertedSize = jpgData.Length; var fileName = Path.GetFileNameWithoutExtension(webpFile.FileName) + ".jpg"; _logger.LogInformation("[JPG-WEBP-CONVERTER] Conversão WebP→JPG concluída: {OutputFileName} (Original: {OriginalSize}bytes → Convertido: {ConvertedSize}bytes)", fileName, originalSize, convertedSize); // Se é request de preview e o arquivo não é muito grande if (preview && originalSize <= maxPreviewSize && convertedSize <= maxPreviewSize) { var base64 = Convert.ToBase64String(jpgData); var base64DataUrl = $"data:image/jpeg;base64,{base64}"; return Json(new { success = true, base64 = base64DataUrl, filename = fileName, originalSize = originalSize, convertedSize = convertedSize }); } // Download normal return File(jpgData, "image/jpeg", fileName); } catch (UnknownImageFormatException) { _logger.LogWarning("[JPG-WEBP-CONVERTER] O arquivo WebP parece ser inválido ou o formato não é suportado."); if (preview) { return Json(new { success = false, message = "Arquivo WebP inválido ou formato não suportado." }); } ModelState.AddModelError("webpFile", "Arquivo WebP inválido ou formato não suportado."); ViewBag.ConversionError = "Arquivo WebP inválido ou formato não suportado."; PrepareIndexView(); return View("Index"); } catch (Exception ex) { _logger.LogError(ex, "[JPG-WEBP-CONVERTER] Erro ao converter WebP para JPG: {FileName}", webpFile.FileName); if (preview) { return Json(new { success = false, message = _localizer["ProcessingError"].Value }); } ModelState.AddModelError("webpFile", _localizer["ProcessingError"]); ViewBag.ConversionError = _localizer["ProcessingError"]; PrepareIndexView(); return View("Index"); } } } }