Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions ManagedCode.Storage.AspNetExtensions/FormFileExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using ManagedCode.Storage.Core;
Expand All @@ -10,15 +11,16 @@ public static class FormFileExtensions
{
public static async Task<LocalFile> ToLocalFileAsync(this IFormFile formFile, CancellationToken cancellationToken = default)
{
LocalFile localFile = new();
var tempPath = Path.GetTempPath();
LocalFile localFile = new($"{tempPath}/{formFile.Name}");

await formFile.CopyToAsync(localFile.FileStream, cancellationToken);

return localFile;
}

public static async Task<IEnumerable<LocalFile>> ToLocalFilesAsync(this IFormFileCollection formFileCollection,
CancellationToken cancellationToken)
CancellationToken cancellationToken = default)
{
List<LocalFile> localFiles = new();

Expand Down
4 changes: 2 additions & 2 deletions ManagedCode.Storage.AspNetExtensions/Helpers/MimeHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace ManagedCode.Storage.AspNetExtensions.Helpers;

internal class MimeHelper
public class MimeHelper
{
private static readonly IDictionary<string, string> Mappings = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase)
{
Expand Down Expand Up @@ -569,7 +569,7 @@ internal class MimeHelper
{".zip", "application/x-zip-compressed"},
};

internal static string GetMimeType(string extension)
public static string GetMimeType(string extension)
{
if (!extension.StartsWith("."))
{
Expand Down
24 changes: 18 additions & 6 deletions ManagedCode.Storage.AspNetExtensions/StorageExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using ManagedCode.Storage.AspNetExtensions.Options;
Expand All @@ -14,14 +15,16 @@ public static class StorageExtensions
{
private const int MinLengthForLargeFile = 256 * 1024;

public static async Task UploadToStorageAsync(this IStorage storage, IFormFile formFile, UploadToStorageOptions? options = null,
public static async Task<string> UploadToStorageAsync(this IStorage storage, IFormFile formFile, UploadToStorageOptions? options = null,
CancellationToken cancellationToken = default)
{
options ??= new UploadToStorageOptions();

var extension = Path.GetExtension(formFile.FileName);

BlobMetadata blobMetadata = new()
{
Name = options.UseRandomName ? Guid.NewGuid().ToString("N").ToLowerInvariant() : formFile.FileName,
Name = options.UseRandomName ? $"{Guid.NewGuid().ToString("N").ToLowerInvariant()}{extension}" : formFile.FileName,
ContentType = formFile.ContentType,
Rewrite = options.Rewrite
};
Expand All @@ -39,19 +42,28 @@ public static async Task UploadToStorageAsync(this IStorage storage, IFormFile f
await storage.UploadStreamAsync(blobMetadata, stream, cancellationToken);
}
}

return blobMetadata.Name;
}

public static async Task<FileResult> DownloadAsFileResult(this IStorage storage, string blobName, CancellationToken cancellationToken = default)
{
var localFile = await storage.DownloadAsync(blobName, cancellationToken);

return new FileStreamResult(localFile.FileStream, MimeHelper.GetMimeType(localFile.FileInfo.Extension));
return new FileStreamResult(localFile.FileStream, MimeHelper.GetMimeType(localFile.FileInfo.Extension))
{
FileDownloadName = localFile.FileName
};
}

public static async Task<FileResult> DownloadAsFileResult(this IStorage storage, BlobMetadata blobMetadata, CancellationToken cancellationToken = default)

public static async Task<FileResult> DownloadAsFileResult(this IStorage storage, BlobMetadata blobMetadata,
CancellationToken cancellationToken = default)
{
var localFile = await storage.DownloadAsync(blobMetadata, cancellationToken);

return new FileStreamResult(localFile.FileStream, MimeHelper.GetMimeType(localFile.FileInfo.Extension));
return new FileStreamResult(localFile.FileStream, MimeHelper.GetMimeType(localFile.FileInfo.Extension))
{
FileDownloadName = localFile.FileName
};
}
}
3 changes: 2 additions & 1 deletion ManagedCode.Storage.Core/LocalFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ public LocalFile(string path, bool keepAlive = false)

if (!File.Exists(FilePath))
{
File.Create(FilePath);
var fs = File.Create(FilePath);
fs.Close();
}

FileName = FileInfo.Name;
Expand Down
4 changes: 1 addition & 3 deletions ManagedCode.Storage.FileSystem/FileSystemStorage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public async Task<LocalFile> DownloadAsync(string blobName, CancellationToken ca

var filePath = Path.Combine(_path, blobName);

return new LocalFile(filePath, false);
return new LocalFile(filePath);
}

public async Task<LocalFile> DownloadAsync(BlobMetadata blobMetadata, CancellationToken cancellationToken = default)
Expand Down Expand Up @@ -211,7 +211,6 @@ public async Task UploadAsync(string blobName, string content, CancellationToken
EnsureDirectoryExists();
var filePath = Path.Combine(_path, blobName);

//TODO: Need fix
await Task.Run(() => File.WriteAllText(filePath, content), cancellationToken);
}

Expand All @@ -235,7 +234,6 @@ public async Task UploadAsync(BlobMetadata blobMetadata, byte[] data, Cancellati
EnsureDirectoryExists();
var filePath = Path.Combine(_path, blobMetadata.Name);

//TODO: Need fix
await Task.Run(() => File.WriteAllBytes(filePath, data), cancellationToken);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using FluentAssertions;
using ManagedCode.Storage.AspNetExtensions;
using Microsoft.AspNetCore.Http.Internal;
using Xunit;

namespace ManagedCode.Storage.Tests.AspNetExtensions;

public class FormFileExtensionsTests
{
[Fact]
public async Task ToLocalFileAsync_SmallFile()
{
// Arrange
const int size = 200 * 1024; // 200 KB
var fileName = FileHelper.GenerateRandomFileName("txt");
var formFile = FileHelper.GenerateFormFile(fileName, size);

// Act
var localFile = await formFile.ToLocalFileAsync();

// Assert
localFile.FileStream.Length.Should().Be(formFile.Length);
localFile.FileName.Should().Be(formFile.FileName);
}

[Fact]
public async Task ToLocalFileAsync_LargeFile()
{
// Arrange
const int size = 300 * 1024 * 1024; // 300 MB
var fileName = FileHelper.GenerateRandomFileName("txt");
var formFile = FileHelper.GenerateFormFile(fileName, size);

// Act
var localFile = await formFile.ToLocalFileAsync();

// Assert
localFile.FileStream.Length.Should().Be(formFile.Length);
localFile.FileName.Should().Be(formFile.FileName);
}

[Fact]
public async Task ToLocalFilesAsync_SmallFiles()
{
// Arrange
const int filesCount = 10;
Random random = new();
FormFileCollection collection = new();

for (var i = 0; i < filesCount; i++)
{
var size = random.Next(10, 1000) * 1024;
var fileName = FileHelper.GenerateRandomFileName("txt");
collection.Add(FileHelper.GenerateFormFile(fileName, size));
}

// Act
var localFiles = (await collection.ToLocalFilesAsync()).ToList();

// Assert
localFiles.Count.Should().Be(filesCount);

for (var i = 0; i < filesCount; i++)
{
localFiles[i].FileStream.Length.Should().Be(collection[i].Length);
localFiles[i].FileName.Should().Be(collection[i].FileName);
}
}
}
137 changes: 137 additions & 0 deletions ManagedCode.Storage.Tests/AspNetExtensions/StorageExtensionsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
using System;
using System.IO;
using System.Threading.Tasks;
using FluentAssertions;
using ManagedCode.Storage.AspNetExtensions;
using ManagedCode.Storage.AspNetExtensions.Helpers;
using ManagedCode.Storage.AspNetExtensions.Options;
using ManagedCode.Storage.Core;
using ManagedCode.Storage.Core.Models;
using ManagedCode.Storage.FileSystem.Extensions;
using Microsoft.Extensions.DependencyInjection;
using Xunit;

namespace ManagedCode.Storage.Tests.AspNetExtensions;

public class StorageExtensionsTests
{
public IStorage Storage { get; }
public ServiceProvider ServiceProvider { get; }

public StorageExtensionsTests()
{
ServiceProvider = ConfigureServices();
Storage = ServiceProvider.GetService<IStorage>()!;
}

public static ServiceProvider ConfigureServices()
{
var services = new ServiceCollection();

services.AddFileSystemStorageAsDefault(opt =>
{
opt.CommonPath = Path.Combine(Environment.CurrentDirectory, "managed-code-bucket");
opt.Path = "managed-code-bucket";
});

return services.BuildServiceProvider();
}

[Fact]
public async Task UploadToStorageAsync_SmallFile()
{
// Arrange
const int size = 200 * 1024; // 200 KB
var fileName = FileHelper.GenerateRandomFileName("txt");
var formFile = FileHelper.GenerateFormFile(fileName, size);

// Act
await Storage.UploadToStorageAsync(formFile);
var localFile = await Storage.DownloadAsync(fileName);

// Assert
localFile.FileInfo.Length.Should().Be(formFile.Length);
localFile.FileName.Should().Be(formFile.FileName);

await Storage.DeleteAsync(fileName);
}

[Fact]
public async Task UploadToStorageAsync_LargeFile()
{
// Arrange
const int size = 50 * 1024 * 1024; // 50 MB
var fileName = FileHelper.GenerateRandomFileName("txt");
var formFile = FileHelper.GenerateFormFile(fileName, size);

// Act
await Storage.UploadToStorageAsync(formFile);
var localFile = await Storage.DownloadAsync(fileName);

// Assert
localFile.FileInfo.Length.Should().Be(formFile.Length);
localFile.FileName.Should().Be(formFile.FileName);

await Storage.DeleteAsync(fileName);
}

[Fact]
public async Task UploadToStorageAsync_WithRandomName()
{
// Arrange
const int size = 200 * 1024; // 200 KB
var fileName = FileHelper.GenerateRandomFileName("txt");
var formFile = FileHelper.GenerateFormFile(fileName, size);

// Act
var newFileName = await Storage.UploadToStorageAsync(formFile, new UploadToStorageOptions {UseRandomName = true});
var localFile = await Storage.DownloadAsync(newFileName);

// Assert
localFile.FileInfo.Length.Should().Be(formFile.Length);
localFile.FileName.Should().Be(newFileName);
localFile.FileName.Should().NotBe(formFile.FileName);

await Storage.DeleteAsync(fileName);
}

[Fact]
public async Task DownloadAsFileResult_WithFileName()
{
// Arrange
const int size = 200 * 1024; // 200 KB
var fileName = FileHelper.GenerateRandomFileName("txt");
var localFile = FileHelper.GenerateLocalFile(fileName, size);

// Act
await Storage.UploadFileAsync(fileName, localFile.FilePath);
var fileResult = await Storage.DownloadAsFileResult(fileName);

// Assert
fileResult.ContentType.Should().Be(MimeHelper.GetMimeType(localFile.FileInfo.Extension));
fileResult.FileDownloadName.Should().Be(localFile.FileName);

await Storage.DeleteAsync(fileName);
}

[Fact]
public async Task DownloadAsFileResult_WithBlobMetadata()
{
// Arrange
const int size = 200 * 1024; // 200 KB
var fileName = FileHelper.GenerateRandomFileName("txt");
var localFile = FileHelper.GenerateLocalFile(fileName, size);

BlobMetadata blobMetadata = new() {Name = fileName};

// Act
await Storage.UploadFileAsync(blobMetadata, localFile.FilePath);
var fileResult = await Storage.DownloadAsFileResult(blobMetadata);

// Assert
fileResult.ContentType.Should().Be(MimeHelper.GetMimeType(localFile.FileInfo.Extension));
fileResult.FileDownloadName.Should().Be(localFile.FileName);

await Storage.DeleteAsync(fileName);
}
}
3 changes: 3 additions & 0 deletions ManagedCode.Storage.Tests/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
using Xunit;

[assembly: CollectionBehavior(DisableTestParallelization = true)]
Loading