123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- using System.Diagnostics.CodeAnalysis;
- using ImageConvertService.Biz;
- using ImageConvertService.Biz.Models;
- using ImageConvertService.ExceptionHandling;
- using Microsoft.AspNetCore.Mvc;
- namespace ImageConvertService.Controllers;
- [Route("api/[controller]/[action]")]
- [ApiController]
- public class ConvertToWebpController(ImageConverter converter, ArchiveFileAccessor archiver, PdfImageReader pdf, ArchiveEntrySkipper filter) : Controller
- {
- [HttpPost]
- public IActionResult SingleFile(IFormFile file)
- {
- var ms = new MemoryStream();
- file.CopyTo(ms);
- var bytes = ms.ToArray();
- var webpBytes = converter.ConvertToWebp(bytes);
- return File(webpBytes, "image/webp", $"{file.FileName}.webp");
- }
- [HttpPost]
- public async Task<FileContentResult> AnyArchiveQuery(
- IFormFile file,
- [FromQuery] string? skips,
- [FromQuery] OutputArchiveFormat? format = OutputArchiveFormat.Fast7Z)
- {
- return await AnyArchiveInternal(file.OpenReadStream(), Request.ContentLength, file.FileName, format, skips);
- }
- [HttpPost]
- public async Task<FileContentResult> AnyArchiveForm(
- IFormFile file,
- [FromForm] string? skips,
- [FromForm] OutputArchiveFormat? format = OutputArchiveFormat.Fast7Z)
- {
- return await AnyArchiveInternal(file.OpenReadStream(), Request.ContentLength, file.FileName, format, skips);
- }
- [HttpPost]
- public async Task<FileContentResult> AnyArchiveStreaming(
- [FromQuery] string filename,
- [FromQuery] string? skips,
- [FromQuery] OutputArchiveFormat format = OutputArchiveFormat.Fast7Z)
- {
- return await AnyArchiveInternal(Request.Body, Request.ContentLength, filename, format, skips);
- }
- private async Task<FileContentResult> AnyArchiveInternal(Stream inputStream, long? contentLength, string fileName, OutputArchiveFormat? format, string? skips)
- {
- format ??= OutputArchiveFormat.Fast7Z;
- if (inputStream.CanSeek)
- {
- inputStream.Position = 0;
- return ProcessArchiveInternal(inputStream, fileName, skips, format.Value);
- }
- try
- {
- contentLength = inputStream.Length;
- }
- catch (NotSupportedException)
- {
- }
- if (contentLength.HasValue && contentLength.Value < 2_000_000_000)
- {
- var ms = new MemoryStream();
- await inputStream.CopyToAsync(ms);
- ms.Position = 0;
- return ProcessArchiveInternal(ms, fileName, skips, format.Value);
- }
- await using var tmpFileStream = new FileStream(Path.GetTempFileName(), FileMode.Create, FileAccess.ReadWrite, FileShare.None, 4096, FileOptions.DeleteOnClose);
- await inputStream.CopyToAsync(tmpFileStream);
- tmpFileStream.Position = 0;
- return ProcessArchiveInternal(tmpFileStream, fileName, skips, format.Value);
- }
- private FileContentResult ProcessArchiveInternal(Stream ms, string fileName, string? skips, OutputArchiveFormat format)
- {
- var (direct, convert) = filter.Filter(archiver.ReadArchive(ms), skips);
- var hasError = false;
- var pdfFiles = convert.Where(p => p.PathAndName.EndsWith(".pdf", StringComparison.OrdinalIgnoreCase)).ToArray();
- if (pdfFiles.Length != 0)
- {
- foreach (var pdfFile in pdfFiles)
- {
- var pdfImagesToWebp = pdf.ReadImages(pdfFile.Content, fileTime: pdfFile.FileTimeTuple).ToList();
- hasError |= (!converter.ConvertToWebp(pdfImagesToWebp));
- var pdfToWebpEntry = new ArchiveEntry { FileTimeTuple = pdfFile.FileTimeTuple };
- switch (format)
- {
- case OutputArchiveFormat.Fast7Z:
- pdfToWebpEntry.Content = archiver.MakeArchiveFast7Z(pdfImagesToWebp);
- pdfToWebpEntry.PathAndName = pdfFile.PathAndName + "-webp.7z";
- break;
- case OutputArchiveFormat.FastZip:
- pdfToWebpEntry.Content = archiver.MakeArchiveFastZip(pdfImagesToWebp);
- pdfToWebpEntry.PathAndName = pdfFile.PathAndName + "-webp.zip";
- break;
- default:
- throw new UserFriendlyException($"Invalid {nameof(OutputArchiveFormat)}");
- }
- convert.Remove(pdfFile);
- direct.Add(pdfToWebpEntry);
- }
- }
- hasError |= (!converter.ConvertToWebp(convert));
- direct.AddRange(convert);
- return OutputAsArchive(fileName, format, direct, hasError);
- }
- private FileContentResult OutputAsArchive(string filename, OutputArchiveFormat format, List<ArchiveEntry> direct, bool withErrors)
- {
- return format switch
- {
- OutputArchiveFormat.Fast7Z => File(archiver.MakeArchiveFast7Z(direct), "application/x-7z-compressed", $"{filename}-webp{(withErrors ? "-withErrors" : "")}.7z"),
- OutputArchiveFormat.FastZip => File(archiver.MakeArchiveFastZip(direct), "application/zip", $"{filename}-webp{(withErrors ? "" : "-withErrors")}.zip"),
- _ => throw new UserFriendlyException($"Invalid {nameof(OutputArchiveFormat)}")
- };
- }
- public enum OutputArchiveFormat
- {
- Fast7Z,
- FastZip
- }
- }
|