262 lines
8.4 KiB
C#
262 lines
8.4 KiB
C#
using Microsoft.Extensions.Logging;
|
|
|
|
using DomainResults.Common;
|
|
|
|
using MongoDB.Driver;
|
|
using MongoDB.Driver.GridFS;
|
|
using DataProviders.Buckets.Abstractions;
|
|
using MongoDB.Bson;
|
|
using Extensions;
|
|
|
|
namespace DataProviders.Buckets {
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public interface IImageBucketDataProvider {
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="siteId"></param>
|
|
/// <param name="userId"></param>
|
|
/// <param name="file"></param>
|
|
/// <returns></returns>
|
|
(Guid?, IDomainResult) Upload(BucketFile file);
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="siteId"></param>
|
|
/// <param name="userId"></param>
|
|
/// <param name="files"></param>
|
|
/// <returns></returns>
|
|
(List<Guid>?, IDomainResult) UploadMany(List<BucketFile> files);
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="siteId"></param>
|
|
/// <param name="fileId"></param>
|
|
/// <returns></returns>
|
|
(BucketFile?, IDomainResult) Download(Guid siteId, Guid fileId);
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="siteId"></param>
|
|
/// <param name="userId"></param>
|
|
/// <param name="fileId"></param>
|
|
/// <returns></returns>
|
|
(BucketFile?, IDomainResult) Download(Guid siteId, Guid userId, Guid fileId);
|
|
|
|
|
|
(List<BucketFile>?, IDomainResult) DownloadMany(Guid siteId, Guid userId, List<Guid> fileIds);
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="siteId"></param>
|
|
/// <param name="userId"></param>
|
|
/// <param name="fileId"></param>
|
|
/// <returns></returns>
|
|
IDomainResult DeleteOne(Guid siteId, Guid userId, Guid fileId);
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="siteId"></param>
|
|
/// <param name="userId"></param>
|
|
/// <returns></returns>
|
|
IDomainResult DeleteMany(Guid siteId, Guid userId);
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public class ImageBucketDataProvider : BucketDataProviderBase, IImageBucketDataProvider {
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="logger"></param>
|
|
/// <param name="client"></param>
|
|
public ImageBucketDataProvider(
|
|
ILogger<BucketDataProviderBase> logger,
|
|
IMongoClient client
|
|
) : base(logger, client, "reactredux", "images") { }
|
|
|
|
#region Upload many
|
|
protected override async Task<(List<Guid>?, IDomainResult)> UploadManyAsync(List<BucketFile> files) {
|
|
var options = new GridFSUploadOptions {
|
|
ChunkSizeBytes = 64512, // 63KB
|
|
};
|
|
|
|
try {
|
|
var result = new List<Guid>();
|
|
foreach (var file in files) {
|
|
options.Metadata = new BsonDocument {
|
|
{ "siteId", $"{file.SiteId}"},
|
|
{ "userId", $"{file.UserId}"},
|
|
{ "published", file.Published.ToString() },
|
|
{ "fileName", file.Name },
|
|
{ "contentType", file.ContentType }
|
|
};
|
|
|
|
await _bucket.UploadFromBytesAsync($"{file.Id}", file.Bytes, options);
|
|
result.Add(file.Id);
|
|
}
|
|
|
|
return result.Count > 0
|
|
? IDomainResult.Success(result)
|
|
: IDomainResult.Failed<List<Guid>?>();
|
|
}
|
|
catch (Exception ex) {
|
|
_logger.LogError(ex, "Bucket data provider error");
|
|
return IDomainResult.Failed<List<Guid>?>();
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Download
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="siteId"></param>
|
|
/// <param name="fileId"></param>
|
|
/// <returns></returns>
|
|
public (BucketFile?, IDomainResult) Download(Guid siteId, Guid fileId) {
|
|
var filter = Builders<GridFSFileInfo>.Filter.And(
|
|
Builders<GridFSFileInfo>.Filter.Eq(x => x.Metadata["siteId"], $"{siteId}"),
|
|
Builders<GridFSFileInfo>.Filter.Not(Builders<GridFSFileInfo>.Filter.Eq(x => x.Metadata["published"], "")),
|
|
Builders<GridFSFileInfo>.Filter.Eq(x => x.Filename, $"{fileId}")
|
|
);
|
|
|
|
var (list, result) = Download(filter);
|
|
|
|
if (!result.IsSuccess || list == null)
|
|
return (null, result);
|
|
|
|
return (list.First(), result);
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="siteId"></param>
|
|
/// <param name="userId"></param>
|
|
/// <param name="fileId"></param>
|
|
/// <returns></returns>
|
|
public (BucketFile?, IDomainResult) Download(Guid siteId, Guid userId, Guid fileId) {
|
|
|
|
var filter = Builders<GridFSFileInfo>.Filter.And(
|
|
Builders<GridFSFileInfo>.Filter.Eq(x => x.Metadata["siteId"], $"{siteId}"),
|
|
Builders<GridFSFileInfo>.Filter.Eq(x => x.Metadata["userId"], $"{userId}"),
|
|
Builders<GridFSFileInfo>.Filter.Eq(x => x.Filename, $"{fileId}")
|
|
);
|
|
|
|
var (list, result) = Download(filter);
|
|
|
|
if (!result.IsSuccess || list == null)
|
|
return (null, result);
|
|
|
|
return (list.First(), result);
|
|
}
|
|
#endregion
|
|
|
|
#region Download many
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="siteId"></param>
|
|
/// <param name="userId"></param>
|
|
/// <param name="fileId"></param>
|
|
/// <returns></returns>
|
|
public (List<BucketFile>?, IDomainResult) DownloadMany(Guid siteId, Guid userId, List<Guid> fileIds) {
|
|
|
|
var builder = Builders<GridFSFileInfo>.Filter;
|
|
|
|
FilterDefinition<GridFSFileInfo>? filter = default;
|
|
|
|
foreach (var fileId in fileIds) {
|
|
filter |= builder.And(
|
|
Builders<GridFSFileInfo>.Filter.Eq(x => x.Metadata["siteId"], $"{siteId}"),
|
|
Builders<GridFSFileInfo>.Filter.Eq(x => x.Metadata["userId"], $"{userId}"),
|
|
Builders<GridFSFileInfo>.Filter.Eq(x => x.Filename, $"{fileId}")
|
|
);
|
|
}
|
|
|
|
if (filter == null)
|
|
return IDomainResult.Failed<List<BucketFile>?>();
|
|
|
|
var result = Download(filter);
|
|
|
|
return result;
|
|
}
|
|
|
|
protected override async Task<(List<BucketFile>?, IDomainResult)> DownloadAsync(FilterDefinition<GridFSFileInfo> filter) {
|
|
try {
|
|
var sort = Builders<GridFSFileInfo>.Sort.Descending(x => x.UploadDateTime);
|
|
|
|
using var cursor = await _bucket.FindAsync(filter, new GridFSFindOptions {
|
|
Sort = sort,
|
|
});
|
|
|
|
var result = new List<BucketFile>();
|
|
|
|
// fileInfo either has the matching file information or is null
|
|
foreach (var fileInfo in await cursor.ToListAsync()) {
|
|
if (fileInfo == null)
|
|
return IDomainResult.NotFound<List<BucketFile>?>();
|
|
|
|
var id = fileInfo.Filename.ToGuid();
|
|
var userId = fileInfo.Metadata["userId"].ToString()?.ToNullableGuid();
|
|
var siteId = fileInfo.Metadata["siteId"].ToString()?.ToNullableGuid();
|
|
var published = fileInfo.Metadata["published"].ToString()?.ToNullableDateTime();
|
|
var fileName = fileInfo.Metadata["fileName"].ToString() ?? "";
|
|
var bytes = await _bucket.DownloadAsBytesByNameAsync($"{fileInfo.Filename}", new GridFSDownloadByNameOptions {
|
|
Revision = -1
|
|
});
|
|
var contentType = fileInfo.Metadata["contentType"].ToString() ?? "";
|
|
|
|
if (siteId == null || userId == null || bytes == null)
|
|
return IDomainResult.Failed<List<BucketFile>?>();
|
|
|
|
result.Add(new BucketFile(id, siteId.Value, userId.Value, published, fileName, bytes, contentType));
|
|
}
|
|
|
|
return result.Count > 0
|
|
? IDomainResult.Success(result)
|
|
: IDomainResult.NotFound<List<BucketFile>?>();
|
|
|
|
}
|
|
catch (Exception ex) {
|
|
_logger.LogError(ex, "Bucket data provider error");
|
|
return IDomainResult.Failed<List<BucketFile>?>();
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Delete
|
|
public IDomainResult DeleteOne(Guid siteId, Guid userId, Guid fileId) =>
|
|
DeleteOneAsync(siteId, userId, fileId).Result;
|
|
|
|
public Task<IDomainResult> DeleteOneAsync(Guid siteId, Guid userId, Guid fileId) =>
|
|
DeleteAsync(Builders<GridFSFileInfo>.Filter.And(
|
|
Builders<GridFSFileInfo>.Filter.Eq(x => x.Metadata["siteId"], $"{siteId}"),
|
|
Builders<GridFSFileInfo>.Filter.Eq(x => x.Metadata["userId"], $"{userId}"),
|
|
Builders<GridFSFileInfo>.Filter.Eq(x => x.Filename, $"{fileId}")
|
|
));
|
|
|
|
public IDomainResult DeleteMany(Guid siteId, Guid userId) =>
|
|
DeleteManyAsync(siteId, userId).Result;
|
|
|
|
public Task<IDomainResult> DeleteManyAsync(Guid siteId, Guid userId) =>
|
|
DeleteAsync(Builders<GridFSFileInfo>.Filter.And(
|
|
Builders<GridFSFileInfo>.Filter.Eq(x => x.Metadata["siteId"], $"{siteId}"),
|
|
Builders<GridFSFileInfo>.Filter.Eq(x => x.Metadata["userId"], $"{userId}")
|
|
));
|
|
#endregion
|
|
}
|
|
}
|