261 lines
12 KiB
C#
261 lines
12 KiB
C#
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<SharedResource> _localizer;
|
|
private readonly ILogger<JpgToWebpController> _logger;
|
|
|
|
public JpgToWebpController(IStringLocalizer<SharedResource> localizer, ILogger<JpgToWebpController> 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<IActionResult> 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<IActionResult> 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");
|
|
}
|
|
}
|
|
}
|
|
}
|