修复动图不显示 (#586)

This commit is contained in:
Poker 2025-01-01 00:25:26 +08:00 committed by GitHub
parent a5afe2769d
commit a47b5995cb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 18 additions and 15 deletions

View File

@ -24,7 +24,7 @@ using System.Threading.Tasks;
namespace Pixeval.CoreApi.Global.Exception; namespace Pixeval.CoreApi.Global.Exception;
public class MakoNetworkException(string url, bool domainFronting, string? extraMsg, int statusCode) public class MakoNetworkException(string url, bool domainFronting, string? extraMsg, int statusCode)
: MakoException($"Network error while requesting URL: {url}(Domain fronting: {domainFronting}, Status code: {statusCode}) {extraMsg}") : MakoException($"Network error while requesting URL: {url} (Domain fronting: {domainFronting}, Status code: {statusCode}) {extraMsg}")
{ {
public string Url { get; set; } = url; public string Url { get; set; } = url;

View File

@ -24,6 +24,7 @@ using System.IO.Compression;
using System.IO; using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.IO; using Microsoft.IO;
using System.Linq;
namespace Pixeval.Utilities; namespace Pixeval.Utilities;
@ -61,7 +62,7 @@ public static class Streams
return s; return s;
} }
public static async Task<MemoryStream[]> ReadZipAsync(Stream zipStream, bool dispose) public static async Task<IReadOnlyList<MemoryStream>> ReadZipAsync(Stream zipStream, bool dispose)
{ {
if (zipStream is not MemoryStream ms) if (zipStream is not MemoryStream ms)
{ {
@ -71,19 +72,21 @@ public static class Streams
try try
{ {
using var archive = new ZipArchive(ms, ZipArchiveMode.Read); var list = new List<MemoryStream>();
var result = (MemoryStream[])[]; // Dispose ZipArchive会导致ms也被Dispose
await Parallel.ForAsync(0, archive.Entries.Count, new ParallelOptions(), async (i, token) => var archive = new ZipArchive(ms, ZipArchiveMode.Read);
// ZipArchive不支持多线程
foreach (var entry in archive.Entries)
{ {
await using var stream = archive.Entries[i].Open(); await using var stream = entry.Open();
var rms = _recyclableMemoryStreamManager.GetStream(); var s = _recyclableMemoryStreamManager.GetStream();
await stream.CopyToAsync(rms, token); await stream.CopyToAsync(s);
rms.Position = 0; s.Position = 0;
result[i] = rms; list.Add(s);
}); }
if (dispose) if (dispose)
await ms.DisposeAsync(); await ms.DisposeAsync();
return result; return list;
} }
catch (InvalidDataException) catch (InvalidDataException)
{ {

View File

@ -128,14 +128,14 @@ public static partial class IoHelper
public static async Task<Image> UgoiraSaveToImageAsync(this Stream stream, IReadOnlyList<int> delays, IProgress<double>? progress = null, bool dispose = false) public static async Task<Image> UgoiraSaveToImageAsync(this Stream stream, IReadOnlyList<int> delays, IProgress<double>? progress = null, bool dispose = false)
{ {
var streams = await Streams.ReadZipAsync(stream, dispose); var streams = await Streams.ReadZipAsync(stream, dispose);
var average = 50d / streams.Length; var average = 50d / streams.Count;
var progressValue = 0d; var progressValue = 0d;
var images = new Image[streams.Length]; var images = new Image[streams.Count];
var options = new ParallelOptions(); var options = new ParallelOptions();
if (progress is not null) if (progress is not null)
options.TaskScheduler = TaskScheduler.FromCurrentSynchronizationContext(); options.TaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
await Parallel.ForAsync(0, streams.Length, options, async (i, token) => await Parallel.ForAsync(0, streams.Count, options, async (i, token) =>
{ {
var delay = delays.Count > i ? (uint)delays[i] : 10u; var delay = delays.Count > i ? (uint)delays[i] : 10u;
streams[i].Position = 0; streams[i].Position = 0;