Use CryptoStream to convert stream from base64

Should be way more efficient
This commit is contained in:
Bond_009 2023-10-05 23:29:31 +02:00
parent 40f7eb4e8c
commit efc4c305a9
3 changed files with 28 additions and 29 deletions

View File

@ -7,6 +7,7 @@ using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net.Mime; using System.Net.Mime;
using System.Security.Cryptography;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Api.Attributes; using Jellyfin.Api.Attributes;
@ -78,6 +79,9 @@ public class ImageController : BaseJellyfinApiController
_appPaths = appPaths; _appPaths = appPaths;
} }
private static Stream GetFromBase64Stream(Stream inputStream)
=> new CryptoStream(inputStream, new FromBase64Transform(), CryptoStreamMode.Read);
/// <summary> /// <summary>
/// Sets the user image. /// Sets the user image.
/// </summary> /// </summary>
@ -116,8 +120,8 @@ public class ImageController : BaseJellyfinApiController
return BadRequest("Incorrect ContentType."); return BadRequest("Incorrect ContentType.");
} }
var memoryStream = await GetMemoryStream(Request.Body).ConfigureAwait(false); var stream = GetFromBase64Stream(Request.Body);
await using (memoryStream.ConfigureAwait(false)) await using (stream.ConfigureAwait(false))
{ {
// Handle image/png; charset=utf-8 // Handle image/png; charset=utf-8
var mimeType = Request.ContentType?.Split(';').FirstOrDefault(); var mimeType = Request.ContentType?.Split(';').FirstOrDefault();
@ -130,7 +134,7 @@ public class ImageController : BaseJellyfinApiController
user.ProfileImage = new Data.Entities.ImageInfo(Path.Combine(userDataPath, "profile" + extension)); user.ProfileImage = new Data.Entities.ImageInfo(Path.Combine(userDataPath, "profile" + extension));
await _providerManager await _providerManager
.SaveImage(memoryStream, mimeType, user.ProfileImage.Path) .SaveImage(stream, mimeType, user.ProfileImage.Path)
.ConfigureAwait(false); .ConfigureAwait(false);
await _userManager.UpdateUserAsync(user).ConfigureAwait(false); await _userManager.UpdateUserAsync(user).ConfigureAwait(false);
@ -176,8 +180,8 @@ public class ImageController : BaseJellyfinApiController
return BadRequest("Incorrect ContentType."); return BadRequest("Incorrect ContentType.");
} }
var memoryStream = await GetMemoryStream(Request.Body).ConfigureAwait(false); var stream = GetFromBase64Stream(Request.Body);
await using (memoryStream.ConfigureAwait(false)) await using (stream.ConfigureAwait(false))
{ {
// Handle image/png; charset=utf-8 // Handle image/png; charset=utf-8
var mimeType = Request.ContentType?.Split(';').FirstOrDefault(); var mimeType = Request.ContentType?.Split(';').FirstOrDefault();
@ -190,7 +194,7 @@ public class ImageController : BaseJellyfinApiController
user.ProfileImage = new Data.Entities.ImageInfo(Path.Combine(userDataPath, "profile" + extension)); user.ProfileImage = new Data.Entities.ImageInfo(Path.Combine(userDataPath, "profile" + extension));
await _providerManager await _providerManager
.SaveImage(memoryStream, mimeType, user.ProfileImage.Path) .SaveImage(stream, mimeType, user.ProfileImage.Path)
.ConfigureAwait(false); .ConfigureAwait(false);
await _userManager.UpdateUserAsync(user).ConfigureAwait(false); await _userManager.UpdateUserAsync(user).ConfigureAwait(false);
@ -372,12 +376,12 @@ public class ImageController : BaseJellyfinApiController
return BadRequest("Incorrect ContentType."); return BadRequest("Incorrect ContentType.");
} }
var memoryStream = await GetMemoryStream(Request.Body).ConfigureAwait(false); var stream = GetFromBase64Stream(Request.Body);
await using (memoryStream.ConfigureAwait(false)) await using (stream.ConfigureAwait(false))
{ {
// Handle image/png; charset=utf-8 // Handle image/png; charset=utf-8
var mimeType = Request.ContentType?.Split(';').FirstOrDefault(); var mimeType = Request.ContentType?.Split(';').FirstOrDefault();
await _providerManager.SaveImage(item, memoryStream, mimeType, imageType, null, CancellationToken.None).ConfigureAwait(false); await _providerManager.SaveImage(item, stream, mimeType, imageType, null, CancellationToken.None).ConfigureAwait(false);
await item.UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false); await item.UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false);
return NoContent(); return NoContent();
@ -416,12 +420,12 @@ public class ImageController : BaseJellyfinApiController
return BadRequest("Incorrect ContentType."); return BadRequest("Incorrect ContentType.");
} }
var memoryStream = await GetMemoryStream(Request.Body).ConfigureAwait(false); var stream = GetFromBase64Stream(Request.Body);
await using (memoryStream.ConfigureAwait(false)) await using (stream.ConfigureAwait(false))
{ {
// Handle image/png; charset=utf-8 // Handle image/png; charset=utf-8
var mimeType = Request.ContentType?.Split(';').FirstOrDefault(); var mimeType = Request.ContentType?.Split(';').FirstOrDefault();
await _providerManager.SaveImage(item, memoryStream, mimeType, imageType, null, CancellationToken.None).ConfigureAwait(false); await _providerManager.SaveImage(item, stream, mimeType, imageType, null, CancellationToken.None).ConfigureAwait(false);
await item.UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false); await item.UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false);
return NoContent(); return NoContent();
@ -1792,8 +1796,8 @@ public class ImageController : BaseJellyfinApiController
return BadRequest("Incorrect ContentType."); return BadRequest("Incorrect ContentType.");
} }
var memoryStream = await GetMemoryStream(Request.Body).ConfigureAwait(false); var stream = GetFromBase64Stream(Request.Body);
await using (memoryStream.ConfigureAwait(false)) await using (stream.ConfigureAwait(false))
{ {
var filePath = Path.Combine(_appPaths.DataPath, "splashscreen-upload" + extension); var filePath = Path.Combine(_appPaths.DataPath, "splashscreen-upload" + extension);
var brandingOptions = _serverConfigurationManager.GetConfiguration<BrandingOptions>("branding"); var brandingOptions = _serverConfigurationManager.GetConfiguration<BrandingOptions>("branding");
@ -1803,7 +1807,7 @@ public class ImageController : BaseJellyfinApiController
var fs = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); var fs = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
await using (fs.ConfigureAwait(false)) await using (fs.ConfigureAwait(false))
{ {
await memoryStream.CopyToAsync(fs, CancellationToken.None).ConfigureAwait(false); await stream.CopyToAsync(fs, CancellationToken.None).ConfigureAwait(false);
} }
return NoContent(); return NoContent();
@ -1833,15 +1837,6 @@ public class ImageController : BaseJellyfinApiController
return NoContent(); return NoContent();
} }
private static async Task<MemoryStream> GetMemoryStream(Stream inputStream)
{
using var reader = new StreamReader(inputStream);
var text = await reader.ReadToEndAsync().ConfigureAwait(false);
var bytes = Convert.FromBase64String(text);
return new MemoryStream(bytes, 0, bytes.Length, false, true);
}
private ImageInfo? GetImageInfo(BaseItem item, ItemImageInfo info, int? imageIndex) private ImageInfo? GetImageInfo(BaseItem item, ItemImageInfo info, int? imageIndex)
{ {
int? width = null; int? width = null;

View File

@ -6,6 +6,7 @@ using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net.Mime; using System.Net.Mime;
using System.Security.Cryptography;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -405,9 +406,8 @@ public class SubtitleController : BaseJellyfinApiController
[FromBody, Required] UploadSubtitleDto body) [FromBody, Required] UploadSubtitleDto body)
{ {
var video = (Video)_libraryManager.GetItemById(itemId); var video = (Video)_libraryManager.GetItemById(itemId);
var data = Convert.FromBase64String(body.Data); var stream = new CryptoStream(Request.Body, new FromBase64Transform(), CryptoStreamMode.Read);
var memoryStream = new MemoryStream(data, 0, data.Length, false, true); await using (stream.ConfigureAwait(false))
await using (memoryStream.ConfigureAwait(false))
{ {
await _subtitleManager.UploadSubtitle( await _subtitleManager.UploadSubtitle(
video, video,
@ -417,7 +417,7 @@ public class SubtitleController : BaseJellyfinApiController
Language = body.Language, Language = body.Language,
IsForced = body.IsForced, IsForced = body.IsForced,
IsHearingImpaired = body.IsHearingImpaired, IsHearingImpaired = body.IsHearingImpaired,
Stream = memoryStream Stream = stream
}).ConfigureAwait(false); }).ConfigureAwait(false);
_providerManager.QueueRefresh(video.Id, new MetadataRefreshOptions(new DirectoryService(_fileSystem)), RefreshPriority.High); _providerManager.QueueRefresh(video.Id, new MetadataRefreshOptions(new DirectoryService(_fileSystem)), RefreshPriority.High);

View File

@ -263,7 +263,11 @@ namespace MediaBrowser.Providers.Manager
var fileStreamOptions = AsyncFile.WriteOptions; var fileStreamOptions = AsyncFile.WriteOptions;
fileStreamOptions.Mode = FileMode.Create; fileStreamOptions.Mode = FileMode.Create;
fileStreamOptions.PreallocationSize = source.Length; if (source.CanSeek)
{
fileStreamOptions.PreallocationSize = source.Length;
}
var fs = new FileStream(path, fileStreamOptions); var fs = new FileStream(path, fileStreamOptions);
await using (fs.ConfigureAwait(false)) await using (fs.ConfigureAwait(false))
{ {