generate thumbnails
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
use crate::rpc::aoba::MediaModel;
|
use crate::{HOST, rpc::aoba::MediaModel};
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Props)]
|
#[derive(PartialEq, Clone, Props)]
|
||||||
pub struct MediaItemProps {
|
pub struct MediaItemProps {
|
||||||
@@ -14,9 +14,9 @@ pub fn MediaItem(props: MediaItemProps) -> Element {
|
|||||||
let id = props.item.media_id.unwrap().value;
|
let id = props.item.media_id.unwrap().value;
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
let src = format!("http://localhost:5164/m/{id}");
|
let src = format!("{HOST}/m/thumb/{id}");
|
||||||
#[cfg(not(debug_assertions))]
|
#[cfg(not(debug_assertions))]
|
||||||
let src = format!("https://aoba.app/m/{id}");
|
let src = format!("https://aoba.app/m/thumb/{id}");
|
||||||
// let url = "https://aoba.app/i/{}";
|
// let url = "https://aoba.app/i/{}";
|
||||||
rsx! {
|
rsx! {
|
||||||
div{
|
div{
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ use dioxus::prelude::*;
|
|||||||
use route::Route;
|
use route::Route;
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
pub const HOST: &'static str = "http://localhost:5164";
|
pub const HOST: &'static str = "http://localhost:8080";
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
pub const RPC_HOST: &'static str = "http://localhost:5164";
|
pub const RPC_HOST: &'static str = "http://localhost:8080";
|
||||||
#[cfg(not(debug_assertions))]
|
#[cfg(not(debug_assertions))]
|
||||||
pub const RPC_HOST: &'static str = "https://grpc.aoba.app:8443";
|
pub const RPC_HOST: &'static str = "https://grpc.aoba.app:8443";
|
||||||
#[cfg(not(debug_assertions))]
|
#[cfg(not(debug_assertions))]
|
||||||
|
|||||||
@@ -12,8 +12,9 @@
|
|||||||
<PackageReference Include="MaybeError" Version="1.1.0" />
|
<PackageReference Include="MaybeError" Version="1.1.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.5" />
|
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.5" />
|
||||||
<PackageReference Include="MongoDB.Driver" Version="3.4.0" />
|
<PackageReference Include="MongoDB.Driver" Version="3.4.0" />
|
||||||
<PackageReference Include="MongoDB.Driver.Core.Extensions.DiagnosticSources" Version="2.0.0" />
|
<PackageReference Include="MongoDB.Driver.Core.Extensions.DiagnosticSources" Version="2.1.0" />
|
||||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.10.0" />
|
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.6" />
|
||||||
|
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.11.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -18,6 +18,11 @@ public class AobaService(IMongoDatabase db)
|
|||||||
return await _media.Find(m => m.Id == id).FirstOrDefaultAsync(cancellationToken);
|
return await _media.Find(m => m.Id == id).FirstOrDefaultAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<Media?> GetMediaFromFileAsync(ObjectId id, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
return await _media.Find(m => m.MediaId == id).FirstOrDefaultAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<PagedResult<Media>> FindMediaAsync(string? query, int page = 1, int pageSize = 100)
|
public async Task<PagedResult<Media>> FindMediaAsync(string? query, int page = 1, int pageSize = 100)
|
||||||
{
|
{
|
||||||
var filter = string.IsNullOrWhiteSpace(query) ? "{}" : Builders<Media>.Filter.Text(query);
|
var filter = string.IsNullOrWhiteSpace(query) ? "{}" : Builders<Media>.Filter.Text(query);
|
||||||
|
|||||||
@@ -4,6 +4,9 @@ using MongoDB.Bson;
|
|||||||
using MongoDB.Driver;
|
using MongoDB.Driver;
|
||||||
using MongoDB.Driver.GridFS;
|
using MongoDB.Driver.GridFS;
|
||||||
|
|
||||||
|
using SixLabors.ImageSharp;
|
||||||
|
using SixLabors.ImageSharp.Processing;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -11,18 +14,42 @@ using System.Text;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AobaCore.Services;
|
namespace AobaCore.Services;
|
||||||
internal class ThumbnailService(IMongoDatabase db, AobaService aobaService)
|
public class ThumbnailService(IMongoDatabase db, AobaService aobaService)
|
||||||
{
|
{
|
||||||
private readonly GridFSBucket _gridfs = new GridFSBucket(db);
|
private readonly GridFSBucket _gridfs = new GridFSBucket(db);
|
||||||
private readonly IMongoCollection<MeidaThumbnail> _thumbnails = db.GetCollection<MeidaThumbnail>("thumbs");
|
private readonly IMongoCollection<MeidaThumbnail> _thumbnails = db.GetCollection<MeidaThumbnail>("thumbs");
|
||||||
|
|
||||||
public async Task<MemoryStream> GetThumbnailAsync(ObjectId id)
|
public async Task<Stream?> GetThumbnailAsync(ObjectId id, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
var media = await aobaService.GetMediaAsync(id);
|
||||||
|
if (media == null)
|
||||||
|
return null;
|
||||||
|
if (media.MediaType != MediaType.Image)
|
||||||
|
return null;
|
||||||
|
using var file = await _gridfs.OpenDownloadStreamAsync(media.MediaId, new GridFSDownloadOptions { Seekable = true });
|
||||||
|
return await GenerateThumbnailAsync(file, cancellationToken);
|
||||||
|
}
|
||||||
|
public async Task<Stream?> GetThumbnailFromFileAsync(ObjectId id, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var media = await aobaService.GetMediaFromFileAsync(id);
|
||||||
|
if (media == null)
|
||||||
|
return null;
|
||||||
|
if (media.MediaType != MediaType.Image)
|
||||||
|
return null;
|
||||||
|
using var file = await _gridfs.OpenDownloadStreamAsync(media.MediaId, new GridFSDownloadOptions { Seekable = true });
|
||||||
|
return await GenerateThumbnailAsync(file, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task GenerateThumbnailAsync(ObjectId id)
|
public async Task<Stream> GenerateThumbnailAsync(Stream stream, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
|
var img = Image.Load(stream);
|
||||||
|
img.Mutate(o =>
|
||||||
|
{
|
||||||
|
o.Resize(200, 200);
|
||||||
|
});
|
||||||
|
var result = new MemoryStream();
|
||||||
|
await img.SaveAsWebpAsync(result, cancellationToken);
|
||||||
|
result.Position = 0;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Isopoh.Cryptography.Argon2" Version="2.0.0" />
|
<PackageReference Include="Isopoh.Cryptography.Argon2" Version="2.0.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.5" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.5" />
|
||||||
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.10.0" />
|
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.11.0" />
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.21.2" />
|
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.21.2" />
|
||||||
<PackageReference Include="MimeTypesMap" Version="1.0.9" />
|
<PackageReference Include="MimeTypesMap" Version="1.0.9" />
|
||||||
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.12.0" />
|
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.12.0" />
|
||||||
|
|||||||
@@ -44,9 +44,11 @@ public class MediaController(AobaService aobaService, ILogger<MediaController> l
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("thumb/{id}")]
|
[HttpGet("thumb/{id}")]
|
||||||
public async Task<IActionResult> ThumbAsync(ObjectId id)
|
public async Task<IActionResult> ThumbAsync(ObjectId id, [FromServices] ThumbnailService thumbnailService, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
var thumb = await thumbnailService.GetThumbnailFromFileAsync(id, cancellationToken);
|
||||||
return NoContent();
|
if (thumb == null)
|
||||||
|
return NotFound();
|
||||||
|
return File(thumb, "image/webp", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ public static class OpenTelemetry
|
|||||||
|
|
||||||
public static IEndpointRouteBuilder MapObserability(this IEndpointRouteBuilder endpoints)
|
public static IEndpointRouteBuilder MapObserability(this IEndpointRouteBuilder endpoints)
|
||||||
{
|
{
|
||||||
endpoints.MapPrometheusScrapingEndpoint().RequireAuthorization(p => p.RequireRole("metrics"));
|
endpoints.MapPrometheusScrapingEndpoint().RequireAuthorization();
|
||||||
return endpoints;
|
return endpoints;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,10 +60,6 @@ builder.Services.AddCors(o =>
|
|||||||
p.AllowAnyHeader();
|
p.AllowAnyHeader();
|
||||||
p.WithExposedHeaders("Grpc-Status", "Grpc-Message", "Grpc-Encoding", "Grpc-Accept-Encoding");
|
p.WithExposedHeaders("Grpc-Status", "Grpc-Message", "Grpc-Encoding", "Grpc-Accept-Encoding");
|
||||||
p.AllowAnyOrigin();
|
p.AllowAnyOrigin();
|
||||||
//#if DEBUG
|
|
||||||
//#else
|
|
||||||
// p.WithOrigins("https://aoba.app", "https://grpc.aoba.app");
|
|
||||||
//#endif
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user