diff --git a/osu.Game/Database/ImportTask.cs b/osu.Game/Database/ImportTask.cs
index 1433a567a9..1fb5a42630 100644
--- a/osu.Game/Database/ImportTask.cs
+++ b/osu.Game/Database/ImportTask.cs
@@ -47,10 +47,30 @@ namespace osu.Game.Database
///
public ArchiveReader GetReader()
{
- if (Stream != null)
- return new ZipArchiveReader(Stream, Path);
+ return Stream != null
+ ? getReaderFrom(Stream)
+ : getReaderFrom(Path);
+ }
- return getReaderFrom(Path);
+ ///
+ /// Creates an from a stream.
+ ///
+ /// A seekable stream containing the archive content.
+ /// A reader giving access to the archive's content.
+ private ArchiveReader getReaderFrom(Stream stream)
+ {
+ if (!(stream is MemoryStream memoryStream))
+ {
+ // This isn't used in any current path. May need to reconsider for performance reasons (ie. if we don't expect the incoming stream to be copied out).
+ byte[] buffer = new byte[stream.Length];
+ stream.Read(buffer, 0, (int)stream.Length);
+ memoryStream = new MemoryStream(buffer);
+ }
+
+ if (ZipUtils.IsZipArchive(memoryStream))
+ return new ZipArchiveReader(memoryStream, Path);
+
+ return new LegacyByteArrayReader(memoryStream.ToArray(), Path);
}
///
diff --git a/osu.Game/IO/Archives/LegacyByteArrayReader.cs b/osu.Game/IO/Archives/LegacyByteArrayReader.cs
index 0c3620403f..ea8ff3bbe0 100644
--- a/osu.Game/IO/Archives/LegacyByteArrayReader.cs
+++ b/osu.Game/IO/Archives/LegacyByteArrayReader.cs
@@ -7,7 +7,7 @@ using System.IO;
namespace osu.Game.IO.Archives
{
///
- /// Allows reading a single file from the provided stream.
+ /// Allows reading a single file from the provided byte array.
///
public class LegacyByteArrayReader : ArchiveReader
{
diff --git a/osu.Game/Utils/ZipUtils.cs b/osu.Game/Utils/ZipUtils.cs
index cd4d876451..eb2d2d3b80 100644
--- a/osu.Game/Utils/ZipUtils.cs
+++ b/osu.Game/Utils/ZipUtils.cs
@@ -9,6 +9,34 @@ namespace osu.Game.Utils
{
public static class ZipUtils
{
+ public static bool IsZipArchive(MemoryStream stream)
+ {
+ try
+ {
+ stream.Seek(0, SeekOrigin.Begin);
+
+ using (var arc = ZipArchive.Open(stream))
+ {
+ foreach (var entry in arc.Entries)
+ {
+ using (entry.OpenEntryStream())
+ {
+ }
+ }
+ }
+
+ return true;
+ }
+ catch (Exception)
+ {
+ return false;
+ }
+ finally
+ {
+ stream.Seek(0, SeekOrigin.Begin);
+ }
+ }
+
public static bool IsZipArchive(string path)
{
if (!File.Exists(path))