Quantcast
Channel: ActiveTopics
Viewing all articles
Browse latest Browse all 72689

How to overwrite a media file with a locale, physical file so it works both with blob and non-blob storage

$
0
0

I can't get Cogworks.Tinifier package working on Umbraco v13 (and have got no solutions here: https://www.facebook.com/groups/umbracowebdevs/posts/2091914831210397/). Therefore I have tried to make my own solution (see code below).

It works a part of the way: When user uploads an image TinifyAPI optimizes it and saves the optimized image in a temporary location (like C:\Users\marti\AppData\Local\Temp\tmpsxjjxj.tmp).

But the part of the code that should overwrite the uploaded, non-optimized image (which is my goal - I don't want the original non-optimized image since it consumes server disc space) does not work. I.e. this part:

using (var fileStream = System.IO.File.OpenRead(tempFilePath))
{
    byte[] fileBytesArray;
    using (var memoryStream = new MemoryStream())
    {
        await fileStream.CopyToAsync(memoryStream);
        fileBytesArray = memoryStream.ToArray();
    }
    var fileBytes = new ByteArrayContent(fileBytesArray);
    var uploadResponse = await httpClient.PutAsync(mediaUrl, fileBytes);
    if (!uploadResponse.IsSuccessStatusCode)
    {
        NotifyUser("Upload Error", $"Failed to upload optimized image.");
    }
}

No error, but also no file is overwritten.

My full code:

using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Notifications;
using Umbraco.Cms.Core.Services;
using TinifyAPI;
using Newtonsoft.Json.Linq;

namespace MartinRud.Notifications
{
    public class MediaNotificationHandler : INotificationHandler<MediaSavedNotification>
    {
        private readonly IMediaService _mediaService;
        private readonly IConfiguration _configuration; 
        private readonly ILogger<MediaNotificationHandler> _logger;
        private readonly IEventMessagesFactory _eventMessagesFactory;
        private readonly IHttpClientFactory _httpClientFactory;
        private readonly string _baseUrl;

        public MediaNotificationHandler(IMediaService mediaService, IConfiguration configuration, ILogger<MediaNotificationHandler> logger, IEventMessagesFactory eventMessagesFactory, IHttpClientFactory httpClientFactory)
        {
            _mediaService = mediaService;
            _configuration = configuration;
            _logger = logger;
            _eventMessagesFactory = eventMessagesFactory;
            _httpClientFactory = httpClientFactory;
            _baseUrl = configuration["MediaBaseUrl"] ?? "https://localhost:44378";
            Tinify.Key = _configuration["TinifierSettings:ApiKey"];
        }

public async void Handle(MediaSavedNotification notification)
{
    var httpClient = _httpClientFactory.CreateClient();

    foreach (var mediaItem in notification.SavedEntities)
    {
        if (mediaItem.ContentType.Alias.Equals("Image"))
        {
            var mediaJson = mediaItem.GetValue<string>("umbracoFile");
            var mediaUrl = ExtractUrlFromJson(mediaJson);

            if (!string.IsNullOrEmpty(mediaUrl))
            {
                if (!Uri.IsWellFormedUriString(mediaUrl, UriKind.Absolute))
                {
                    mediaUrl = new Uri(new Uri(_baseUrl), mediaUrl).ToString();
                }

                _logger.LogInformation($"Attempting to fetch URL: {mediaUrl}");

                var tempFilePath = Path.GetTempFileName();
                var jsonFilePath = Path.ChangeExtension(tempFilePath, "json");

                try
                {
                    var response = await GetWithRetryAsync(httpClient, mediaUrl);

                    if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
                    {
                        NotifyUser("URL Not Found", $"The URL '{mediaUrl}' was not found.");
                        continue;
                    }

                    using (var fileStream = System.IO.File.Create(tempFilePath))
                    {
                        await response.Content.CopyToAsync(fileStream);
                    }

                    if (System.IO.File.Exists(jsonFilePath))
                    {
                        NotifyUser("Image already compressed", "The image has already been optimized.");
                        continue;
                    }

                    NotifyUser("Starting image optimization", $"Starting optimization for image '{mediaItem.Name}'");
                    _logger.LogInformation("Calling CompressImage for: {TempFilePath}", tempFilePath);

                    await CompressImage(tempFilePath, jsonFilePath);

                    _logger.LogInformation("Finished calling CompressImage for: {TempFilePath}", tempFilePath);

                    // Upload the optimized image
                    using (var fileStream = System.IO.File.OpenRead(tempFilePath))
                    {
                        byte[] fileBytesArray;
                        using (var memoryStream = new MemoryStream())
                        {
                            await fileStream.CopyToAsync(memoryStream);
                            fileBytesArray = memoryStream.ToArray();
                        }
                        var fileBytes = new ByteArrayContent(fileBytesArray);
                        var uploadResponse = await httpClient.PutAsync(mediaUrl, fileBytes);
                        if (!uploadResponse.IsSuccessStatusCode)
                        {
                            NotifyUser("Upload Error", $"Failed to upload optimized image.");
                        }
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Error processing media item for: {MediaItemName}", mediaItem.Name);
                    NotifyUser("Error", $"Error processing media item: {ex.Message}");
                }
                finally
                {
                    // Clean up temporary files
                    try
                    {
                        if (System.IO.File.Exists(tempFilePath))
                        {
                            //System.IO.File.Delete(tempFilePath);
                            _logger.LogInformation("Deleted temporary file: {TempFilePath}", tempFilePath);
                        }
                        if (System.IO.File.Exists(jsonFilePath))
                        {
                            //System.IO.File.Delete(jsonFilePath);
                            _logger.LogInformation("Deleted JSON file: {JsonFilePath}", jsonFilePath);
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, "Error deleting temporary files.");
                    }
                }
            }
        }
    }
}


private string ExtractUrlFromJson(string json)
{
    try
    {
        var jsonObject = JObject.Parse(json);
        var url = jsonObject["src"]?.ToString();
        return url ?? string.Empty;
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Error parsing JSON for media URL");
        return string.Empty;
    }
}

private async Task<HttpResponseMessage> GetWithRetryAsync(HttpClient httpClient, string url, int maxRetries = 3)
{
    for (int retry = 0; retry < maxRetries; retry++)
    {
        try
        {
            var response = await httpClient.GetAsync(url);
            response.EnsureSuccessStatusCode(); // Throws if not success code.
            return response;
        }
        catch (HttpRequestException ex)
        {
            if (retry == maxRetries - 1) // Last retry
            {
                _logger.LogError(ex, "Error fetching URL: {Url}", url);
                throw;
            }
            await Task.Delay(1000); // Wait before retrying
        }
    }
    throw new Exception("Failed to fetch URL after multiple retries.");
}
        private async Task CompressImage(string filePath, string jsonFilePath)
        {
            try
            {
                var originalSize = new FileInfo(filePath).Length;
                var source = Tinify.FromFile(filePath);
                await source.ToFile(filePath);

                var compressedSize = new FileInfo(filePath).Length;
                var percentageReduction = (double)(originalSize - compressedSize) / originalSize * 100;

                var compressionInfo = new
                {
                    OriginalSize = originalSize,
                    CompressedSize = compressedSize,
                    PercentageReduction = Math.Round(percentageReduction, 2)
                };

                var json = JObject.FromObject(compressionInfo);
                await System.IO.File.WriteAllTextAsync(jsonFilePath, json.ToString());

                NotifyUser("Image optimization complete", $"Optimization for image completed successfully.");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error compressing image");
                NotifyUser("Image optimization error", $"Error optimizing image: {ex.Message}");
            }
        }

        private void NotifyUser(string title, string message)
        {
            var eventMessages = _eventMessagesFactory.Get();
            eventMessages.Add(new EventMessage(title, message, EventMessageType.Success)); // or .Error if needed
        }
    }
}

Viewing all articles
Browse latest Browse all 72689

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>