Families.Web
1.0.0.0
사진, 동영상, 글, 댓글과 반응을 가족끼리만 공유하는 비공개 앨범·타임라인 서비스입니다.
Toggle main menu visibility
로딩중...
검색중...
일치하는것 없음
LocalMediaService.cs
이 파일의 문서화 페이지로 가기
1
using
System.IO;
2
using
FamiliesApp.Models
;
3
using
Microsoft.AspNetCore.Components.Forms;
4
5
namespace
FamiliesApp.Services
;
6
15
public
sealed
class
LocalMediaService
:
IMediaService
16
{
25
private
readonly
IFamilyTenantStore
_tenants
;
34
private
readonly
IGlobalSettingsStore
_globalSettings
;
35
44
private
static
readonly
string
[]
AllowedImageExts
= [
".jpg"
,
".jpeg"
,
".png"
,
".webp"
,
".gif"
];
53
private
static
readonly
string
[]
AllowedVideoExts
= [
".mp4"
,
".webm"
,
".mov"
,
".m4v"
];
54
79
public
LocalMediaService
(
IFamilyTenantStore
tenants,
IGlobalSettingsStore
globalSettings)
80
{
81
_tenants
= tenants;
82
_globalSettings
= globalSettings;
83
}
84
109
private
static
long
ToBytes
(
int
mb) => mb <= 0 ? long.MaxValue : mb * 1024L * 1024L;
110
143
private
async Task<(
long
ImageBytes,
long
VideoBytes)>
GetLimitsAsync
(
string
slug, CancellationToken ct)
144
{
145
var config = await
_tenants
.GetAsync(slug, ct).ConfigureAwait(
false
);
146
var settings = await
_globalSettings
.GetAsync(ct).ConfigureAwait(
false
);
147
148
var imageMb = config?.MaxImageSizeMb ?? settings.MaxImageSizeMb;
149
var videoMb = config?.MaxVideoSizeMb ?? settings.MaxVideoSizeMb;
150
return
(
ToBytes
(imageMb),
ToBytes
(videoMb));
151
}
152
209
public
async Task<string>
UploadPostMediaAsync
(
string
slug,
string
postId, IBrowserFile file, CancellationToken ct =
default
)
210
{
211
var ext = Path.GetExtension(file.Name).ToLowerInvariant();
212
bool
isVideo = Array.Exists(
AllowedVideoExts
, e => e == ext);
213
bool
isImage = Array.Exists(
AllowedImageExts
, e => e == ext);
214
215
if
(!isVideo && !isImage)
216
throw
new
InvalidOperationException($
"허용되지 않는 파일 형식입니다: {ext}"
);
217
218
var (imageLimit, videoLimit) = await
GetLimitsAsync
(slug, ct).ConfigureAwait(
false
);
219
var limit = isVideo ? videoLimit : imageLimit;
220
if
(file.Size > limit)
221
throw
new
InvalidOperationException(isVideo
222
? $
"동영상은 {FormatLimit(videoLimit)} 이하여야 합니다."
223
: $
"이미지는 {FormatLimit(imageLimit)} 이하여야 합니다."
);
224
225
var mediaDir = Path.Combine(
_tenants
.GetTenantDataPath(slug),
"media"
, postId);
226
Directory.CreateDirectory(mediaDir);
227
228
var fileName = $
"{DateTime.Now:yyyyMMdd_HHmmss}_{Guid.NewGuid():N}{ext}"
;
229
var destPath = Path.Combine(mediaDir, fileName);
230
231
await
using
var dest = File.Create(destPath);
232
await file.OpenReadStream(limit, ct).CopyToAsync(dest, ct).ConfigureAwait(
false
);
233
234
return
fileName;
235
}
236
285
public
async Task<string>
UploadCoverAsync
(
string
slug, IBrowserFile file, CancellationToken ct =
default
)
286
{
287
var ext = Path.GetExtension(file.Name).ToLowerInvariant();
288
if
(!Array.Exists(
AllowedImageExts
, e => e == ext))
289
throw
new
InvalidOperationException($
"허용되지 않는 이미지 형식입니다: {ext}"
);
290
291
var (imageLimit, _) = await
GetLimitsAsync
(slug, ct).ConfigureAwait(
false
);
292
if
(file.Size > imageLimit)
293
throw
new
InvalidOperationException($
"커버 이미지는 {FormatLimit(imageLimit)} 이하여야 합니다."
);
294
295
var dir =
_tenants
.GetTenantDataPath(slug);
296
Directory.CreateDirectory(dir);
297
298
var fileName = $
"cover{ext}"
;
299
await
using
var dest = File.Create(Path.Combine(dir, fileName));
300
await file.OpenReadStream(imageLimit, ct).CopyToAsync(dest, ct).ConfigureAwait(
false
);
301
302
var config = await
_tenants
.GetAsync(slug, ct).ConfigureAwait(
false
) ??
new
Models.FamilyConfig
{ Slug = slug };
303
config.CoverImageFileName = fileName;
304
await
_tenants
.SaveAsync(config, ct).ConfigureAwait(
false
);
305
306
return
fileName;
307
}
308
333
private
static
string
FormatLimit
(
long
bytes) =>
334
bytes == long.MaxValue ?
"무제한"
: $
"{bytes / (1024 * 1024)}MB"
;
335
384
public
Task
DeletePostMediaAsync
(
string
slug,
string
postId,
string
fileName, CancellationToken ct =
default
)
385
{
386
var path = Path.Combine(
_tenants
.GetTenantDataPath(slug),
"media"
, postId, fileName);
387
if
(File.Exists(path)) File.Delete(path);
388
return
Task.CompletedTask;
389
}
390
431
public
Task<IReadOnlyList<MediaInfo>>
GetPostMediaAsync
(
string
slug,
string
postId, CancellationToken ct =
default
)
432
{
433
var dir = Path.Combine(
_tenants
.GetTenantDataPath(slug),
"media"
, postId);
434
if
(!Directory.Exists(dir))
return
Task.FromResult<IReadOnlyList<MediaInfo>>([]);
435
436
var list = Directory.GetFiles(dir)
437
.Select(f =>
438
{
439
var fi =
new
FileInfo(f);
440
return
new
MediaInfo
441
{
442
FileName = fi.Name,
443
Url =
GetMediaUrl
(slug, postId, fi.Name),
444
ThumbUrl =
GetThumbUrl
(slug, postId, fi.Name),
445
SizeBytes = fi.Length,
446
LastModified = fi.LastWriteTime
447
};
448
})
449
.ToList();
450
451
return
Task.FromResult<IReadOnlyList<MediaInfo>>(list);
452
}
453
494
public
string
GetMediaUrl
(
string
slug,
string
postId,
string
fileName) =>
495
$
"/family-data/{slug}/media/{postId}/{Uri.EscapeDataString(fileName)}"
;
496
537
public
string
GetThumbUrl
(
string
slug,
string
postId,
string
fileName) =>
538
GetMediaUrl
(slug, postId, fileName);
539
572
public
string
GetCoverUrl
(
string
slug,
string
fileName) =>
573
$
"/family-data/{slug}/{Uri.EscapeDataString(fileName)}"
;
574
}
FamiliesApp.Models
Definition
AlbumInfo.cs:1
FamiliesApp.Services
Definition
FamilyOptions.cs:4
FamiliesApp.Models.FamilyConfig
Definition
FamilyConfig.cs:12
FamiliesApp.Models.MediaInfo
Definition
MediaInfo.cs:12
FamiliesApp.Services.IFamilyTenantStore
Definition
IFamilyTenantStore.cs:14
FamiliesApp.Services.IGlobalSettingsStore
Definition
IGlobalSettingsStore.cs:14
FamiliesApp.Services.IMediaService
Definition
IMediaService.cs:15
FamiliesApp.Services.LocalMediaService.DeletePostMediaAsync
Task DeletePostMediaAsync(string slug, string postId, string fileName, CancellationToken ct=default)
Definition
LocalMediaService.cs:384
FamiliesApp.Services.LocalMediaService.ToBytes
static long ToBytes(int mb)
Definition
LocalMediaService.cs:109
FamiliesApp.Services.LocalMediaService.GetLimitsAsync
async Task<(long ImageBytes, long VideoBytes)> GetLimitsAsync(string slug, CancellationToken ct)
Definition
LocalMediaService.cs:143
FamiliesApp.Services.LocalMediaService.LocalMediaService
LocalMediaService(IFamilyTenantStore tenants, IGlobalSettingsStore globalSettings)
Definition
LocalMediaService.cs:79
FamiliesApp.Services.LocalMediaService._tenants
readonly IFamilyTenantStore _tenants
Definition
LocalMediaService.cs:25
FamiliesApp.Services.LocalMediaService.GetCoverUrl
string GetCoverUrl(string slug, string fileName)
Definition
LocalMediaService.cs:572
FamiliesApp.Services.LocalMediaService.GetThumbUrl
string GetThumbUrl(string slug, string postId, string fileName)
Definition
LocalMediaService.cs:537
FamiliesApp.Services.LocalMediaService.GetPostMediaAsync
Task< IReadOnlyList< MediaInfo > > GetPostMediaAsync(string slug, string postId, CancellationToken ct=default)
Definition
LocalMediaService.cs:431
FamiliesApp.Services.LocalMediaService.UploadCoverAsync
async Task< string > UploadCoverAsync(string slug, IBrowserFile file, CancellationToken ct=default)
Definition
LocalMediaService.cs:285
FamiliesApp.Services.LocalMediaService._globalSettings
readonly IGlobalSettingsStore _globalSettings
Definition
LocalMediaService.cs:34
FamiliesApp.Services.LocalMediaService.AllowedImageExts
static readonly string[] AllowedImageExts
Definition
LocalMediaService.cs:44
FamiliesApp.Services.LocalMediaService.GetMediaUrl
string GetMediaUrl(string slug, string postId, string fileName)
Definition
LocalMediaService.cs:494
FamiliesApp.Services.LocalMediaService.FormatLimit
static string FormatLimit(long bytes)
Definition
LocalMediaService.cs:333
FamiliesApp.Services.LocalMediaService.UploadPostMediaAsync
async Task< string > UploadPostMediaAsync(string slug, string postId, IBrowserFile file, CancellationToken ct=default)
Definition
LocalMediaService.cs:209
FamiliesApp.Services.LocalMediaService.AllowedVideoExts
static readonly string[] AllowedVideoExts
Definition
LocalMediaService.cs:53
Services
LocalMediaService.cs
다음에 의해 생성됨 :
1.17.0