Skip to content

Commit d1c8fde

Browse files
Implement admin batch preprocess of images without thumbnails
1 parent 5c6fa30 commit d1c8fde

File tree

4 files changed

+421
-0
lines changed

4 files changed

+421
-0
lines changed

API/OCM.Net/OCM.API.Core/Common/MediaItemManager.cs

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,5 +222,139 @@ public void DeleteMediaItem(int userId, int mediaItemId)
222222
AuditLogManager.Log(user, AuditEventType.DeletedItem, "{EntityType:\"Comment\", EntityID:" + mediaItemId + ",ChargePointID:" + cpID + "}", "User deleted media item");
223223
}
224224
}
225+
226+
public async Task<List<MediaItem>> GetMediaItemsWithMissingThumbnails(int maxResults = 100)
227+
{
228+
var dataModel = new OCMEntities();
229+
230+
var items = dataModel.MediaItems
231+
.Where(m => m.IsEnabled == true &&
232+
m.ItemUrl != null &&
233+
(m.ItemThumbnailUrl == null || m.ItemThumbnailUrl == "") &&
234+
!m.IsExternalResource &&
235+
!m.IsVideo)
236+
.Take(maxResults)
237+
.ToList();
238+
239+
return items;
240+
}
241+
242+
public async Task<ReprocessMediaResult> ReprocessMediaItem(int mediaItemId, string tempFolderPath)
243+
{
244+
var result = new ReprocessMediaResult { MediaItemId = mediaItemId };
245+
var dataModel = new OCMEntities();
246+
247+
var mediaItem = dataModel.MediaItems.FirstOrDefault(m => m.Id == mediaItemId);
248+
249+
if (mediaItem == null)
250+
{
251+
result.Success = false;
252+
result.Message = "Media item not found";
253+
return result;
254+
}
255+
256+
if (string.IsNullOrEmpty(mediaItem.ItemUrl))
257+
{
258+
result.Success = false;
259+
result.Message = "No original image URL";
260+
return result;
261+
}
262+
263+
if (mediaItem.IsVideo || mediaItem.IsExternalResource)
264+
{
265+
result.Success = false;
266+
result.Message = "Cannot reprocess video or external resources";
267+
return result;
268+
}
269+
270+
// Get POI info for metadata
271+
var poi = await new POIManager().Get(mediaItem.ChargePointId);
272+
if (poi == null)
273+
{
274+
result.Success = false;
275+
result.Message = "Associated charging location not found";
276+
return result;
277+
}
278+
279+
try
280+
{
281+
// Download the original image
282+
string extension = Path.GetExtension(mediaItem.ItemUrl).ToLower();
283+
if (string.IsNullOrEmpty(extension))
284+
{
285+
extension = ".jpg";
286+
}
287+
288+
string tempOriginalFile = Path.Combine(tempFolderPath, $"temp_original_{mediaItemId}{extension}");
289+
290+
using (var client = new System.Net.Http.HttpClient())
291+
{
292+
client.Timeout = TimeSpan.FromMinutes(2);
293+
var imageBytes = await client.GetByteArrayAsync(mediaItem.ItemUrl);
294+
await File.WriteAllBytesAsync(tempOriginalFile, imageBytes);
295+
}
296+
297+
// Generate thumbnails
298+
string destFolderPrefix = poi.AddressInfo.Country.ISOCode + "/" + "OCM" + poi.ID + "/";
299+
string dateStamp = String.Format("{0:yyyyMMddHHmmssff}", DateTime.UtcNow);
300+
string thumbFileName = "OCM-" + poi.ID + ".thmb." + dateStamp + extension;
301+
string mediumFileName = "OCM-" + poi.ID + ".medi." + dateStamp + extension;
302+
303+
string thumbFilePath = Path.Combine(tempFolderPath, thumbFileName);
304+
string mediumFilePath = Path.Combine(tempFolderPath, mediumFileName);
305+
306+
GenerateImageThumbnails(tempOriginalFile, thumbFilePath, 100);
307+
GenerateImageThumbnails(tempOriginalFile, mediumFilePath, 400);
308+
309+
// Upload to storage
310+
var storage = new StorageManager();
311+
var metadataTags = new List<KeyValuePair<string, string>>
312+
{
313+
new KeyValuePair<string, string>("OCM", poi.ID.ToString()),
314+
new KeyValuePair<string, string>("Latitude", poi.AddressInfo.Latitude.ToString()),
315+
new KeyValuePair<string, string>("Longitude", poi.AddressInfo.Longitude.ToString())
316+
};
317+
318+
string thumbnailUrl = await storage.UploadImageAsync(thumbFilePath, destFolderPrefix + thumbFileName, metadataTags);
319+
string mediumUrl = await storage.UploadImageAsync(mediumFilePath, destFolderPrefix + mediumFileName, metadataTags);
320+
321+
// Update database
322+
mediaItem.ItemThumbnailUrl = thumbnailUrl;
323+
await dataModel.SaveChangesAsync();
324+
325+
// Clean up temp files
326+
try
327+
{
328+
File.Delete(tempOriginalFile);
329+
File.Delete(thumbFilePath);
330+
File.Delete(mediumFilePath);
331+
}
332+
catch { }
333+
334+
result.Success = true;
335+
result.Message = "Successfully reprocessed";
336+
result.ThumbnailUrl = thumbnailUrl;
337+
result.MediumUrl = mediumUrl;
338+
339+
AuditLogManager.Log(null, AuditEventType.UpdatedItem, $"Reprocessed media item {mediaItemId}, generated thumbnail: {thumbnailUrl}", "");
340+
}
341+
catch (Exception ex)
342+
{
343+
result.Success = false;
344+
result.Message = $"Error: {ex.Message}";
345+
AuditLogManager.Log(null, AuditEventType.SystemErrorAPI, $"Failed to reprocess media item {mediaItemId}: {ex.Message}", ex.ToString());
346+
}
347+
348+
return result;
349+
}
350+
}
351+
352+
public class ReprocessMediaResult
353+
{
354+
public int MediaItemId { get; set; }
355+
public bool Success { get; set; }
356+
public string Message { get; set; }
357+
public string ThumbnailUrl { get; set; }
358+
public string MediumUrl { get; set; }
225359
}
226360
}

Website/OCM.Web/Controllers/AdminController.cs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Configuration;
4+
using System.IO;
45
using System.Linq;
56
using System.Threading.Tasks;
67
using Microsoft.AspNetCore.Http;
@@ -448,5 +449,85 @@ public async Task<ActionResult> Benchmarks()
448449
var results = await cache.PerformPOIQueryBenchmark(10, "bounding");
449450
return View(results);
450451
}
452+
453+
[Authorize(Roles = "Admin")]
454+
public async Task<ActionResult> MediaItemsWithoutThumbnails()
455+
{
456+
var mediaManager = new MediaItemManager();
457+
var items = await mediaManager.GetMediaItemsWithMissingThumbnails(100);
458+
459+
ViewBag.TotalCount = items.Count;
460+
return View(items);
461+
}
462+
463+
[Authorize(Roles = "Admin")]
464+
[HttpPost]
465+
public async Task<JsonResult> ReprocessMediaItem(int id)
466+
{
467+
var mediaManager = new MediaItemManager();
468+
string tempFolder = Path.Combine(Path.GetTempPath(), "OCM_MediaReprocess");
469+
470+
if (!Directory.Exists(tempFolder))
471+
{
472+
Directory.CreateDirectory(tempFolder);
473+
}
474+
475+
var result = await mediaManager.ReprocessMediaItem(id, tempFolder);
476+
477+
return Json(new
478+
{
479+
success = result.Success,
480+
message = result.Message,
481+
thumbnailUrl = result.ThumbnailUrl,
482+
mediumUrl = result.MediumUrl
483+
});
484+
}
485+
486+
[Authorize(Roles = "Admin")]
487+
[HttpPost]
488+
public async Task<JsonResult> ReprocessAllMissingThumbnails(int batchSize = 10)
489+
{
490+
var mediaManager = new MediaItemManager();
491+
var items = await mediaManager.GetMediaItemsWithMissingThumbnails(batchSize);
492+
493+
string tempFolder = Path.Combine(Path.GetTempPath(), "OCM_MediaReprocess");
494+
if (!Directory.Exists(tempFolder))
495+
{
496+
Directory.CreateDirectory(tempFolder);
497+
}
498+
499+
int successCount = 0;
500+
int failureCount = 0;
501+
var results = new List<object>();
502+
503+
foreach (var item in items)
504+
{
505+
var result = await mediaManager.ReprocessMediaItem(item.Id, tempFolder);
506+
507+
if (result.Success)
508+
{
509+
successCount++;
510+
}
511+
else
512+
{
513+
failureCount++;
514+
}
515+
516+
results.Add(new
517+
{
518+
id = item.Id,
519+
success = result.Success,
520+
message = result.Message
521+
});
522+
}
523+
524+
return Json(new
525+
{
526+
totalProcessed = items.Count,
527+
successCount = successCount,
528+
failureCount = failureCount,
529+
results = results
530+
});
531+
}
451532
}
452533
}

Website/OCM.Web/Views/Admin/Index.cshtml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
<ul>
1515
<li>@Html.ActionLink("Check POI Cache Status", "CheckPOIMirrorStatus", "Admin")</li>
1616
<li>@Html.ActionLink("Benchmark Tests", "Benchmarks", "Admin")</li>
17+
18+
<li>@Html.ActionLink("Fix Media Item Thumbnails", "MediaItemsWithoutThumbnails", "Admin")</li>
1719
</ul>
1820

1921
<h3>Data Import</h3>

0 commit comments

Comments
 (0)