Skip to content

Commit

Permalink
Merge pull request #981 from riganti/async-file-storage
Browse files Browse the repository at this point in the history
IUploadedFileStorage and IReturnedFileStorage made async and moved to DotVVM.Core
  • Loading branch information
quigamdev committed Mar 25, 2021
2 parents 678dfb2 + 9108edf commit 6bdbc01
Show file tree
Hide file tree
Showing 18 changed files with 120 additions and 93 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using DotVVM.Framework.Utils;
using DotVVM.Core.Utils;

namespace DotVVM.Framework.Storage
namespace DotVVM.Core.Storage
{
public class FileSize
{
Expand All @@ -13,4 +13,4 @@ public override string ToString()
return FormattedText;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,24 @@
using System.IO;
using System.Threading.Tasks;

namespace DotVVM.Framework.Storage
namespace DotVVM.Core.Storage
{
public interface IReturnedFileStorage
{
/// <summary>
/// Stores the file and returns its unique ID.
/// </summary>
Task<Guid> StoreFile(Stream stream, ReturnedFileMetadata metadata);
Task<Guid> StoreFileAsync(Stream stream, ReturnedFileMetadata metadata);

/// <summary>
/// Gets the file from the storage.
/// </summary>
Stream GetFile(Guid fileId, out ReturnedFileMetadata metadata);
Task<ReturnedFile> GetFileAsync(Guid fileId);

/// <summary>
/// Deletes the file with the specified ID.
/// </summary>
void DeleteFile(Guid fileId);
Task DeleteFileAsync(Guid fileId);

/// <summary>
/// Deletes all files older than the specified date.
/// </summary>
void DeleteOldFiles(DateTime maxCreatedDate);
}
}
}
25 changes: 25 additions & 0 deletions src/DotVVM.Core/Storage/IUploadedFileStorage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System;
using System.IO;
using System.Threading.Tasks;

namespace DotVVM.Core.Storage
{
public interface IUploadedFileStorage
{
/// <summary>
/// Stores uploaded file and returns its unique ID.
/// </summary>
Task<Guid> StoreFileAsync(Stream stream);

/// <summary>
/// Deletes the uploaded file with the specified ID.
/// </summary>
Task DeleteFileAsync(Guid fileId);

/// <summary>
/// Gets the stream of the file with the specified ID.
/// </summary>
Task<Stream> GetFileAsync(Guid fileId);

}
}
23 changes: 23 additions & 0 deletions src/DotVVM.Core/Storage/ReturnedFile.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DotVVM.Core.Storage
{
public class ReturnedFile
{

public Stream Stream { get; }
public ReturnedFileMetadata Metadata { get; }

public ReturnedFile(Stream stream, ReturnedFileMetadata metadata)
{
Stream = stream;
Metadata = metadata;
}

}
}
12 changes: 12 additions & 0 deletions src/DotVVM.Core/Storage/ReturnedFileMetadata.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System.Collections.Generic;

namespace DotVVM.Core.Storage
{
public class ReturnedFileMetadata
{
public string? FileName { get; set; }
public string? MimeType { get; set; }
public Dictionary<string, string[]> AdditionalHeaders { get; set; } = new Dictionary<string, string[]>();
public string? AttachmentDispositionType { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
using System;

namespace DotVVM.Framework.Storage
namespace DotVVM.Core.Storage
{
public class UploadedFile
{
public Guid FileId { get; set; }

public string FileName { get; set; }
public string? FileName { get; set; }

public FileSize FileSize { get; set; } = new FileSize();

Expand All @@ -17,4 +17,4 @@ public class UploadedFile
public bool IsAllowed
=> IsFileTypeAllowed && !IsMaxSizeExceeded;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
using System;
using System.IO;
using System.Threading.Tasks;

namespace DotVVM.Framework.Storage
namespace DotVVM.Core.Storage
{
public static class UploadedFileStorageExtensions
{
/// <summary>
/// Saves an uploaded file with the specified ID to the given location.
/// </summary>
public static void SaveAs(this IUploadedFileStorage storage, Guid fileId, string path)
public static async Task SaveAsAsync(this IUploadedFileStorage storage, Guid fileId, string path)
{
using (var stream = storage.GetFile(fileId))
using (var stream = await storage.GetFileAsync(fileId))
{
using (var fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write))
{
stream.CopyTo(fs);
await stream.CopyToAsync(fs);
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#nullable enable
namespace DotVVM.Framework.Utils
using DotVVM;

namespace DotVVM.Core.Utils
{
public static class TextUtils
{
Expand Down
2 changes: 1 addition & 1 deletion src/DotVVM.Framework/Controls/UploadedFilesCollection.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#nullable enable
using System.Collections.Generic;
using DotVVM.Framework.Storage;
using DotVVM.Core.Storage;

namespace DotVVM.Framework.Controls
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#nullable enable
using System;
using System.IO;
using DotVVM.Core.Storage;
using DotVVM.Framework.Configuration;
using DotVVM.Framework.Diagnostics;
using DotVVM.Framework.Runtime;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
using System.Threading.Tasks;
using DotVVM.Framework.Routing;
using DotVVM.Framework.Hosting;
using DotVVM.Core.Storage;

public static class DotvvmRequestContextExtensions
{
Expand Down Expand Up @@ -232,7 +233,7 @@ public static void ReturnFile(this IDotvvmRequestContext context, Stream stream,
AttachmentDispositionType = attachmentDispositionType ?? "attachment"
};

var generatedFileId = returnedFileStorage.StoreFile(stream, metadata).Result;
var generatedFileId = returnedFileStorage.StoreFileAsync(stream, metadata).Result;
context.SetRedirectResponse(context.TranslateVirtualPath("~/dotvvmReturnedFile?id=" + generatedFileId));
throw new DotvvmInterruptRequestExecutionException(InterruptReason.ReturnFile, fileName);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
using System.Net;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using DotVVM.Core.Storage;
using DotVVM.Framework.Configuration;
using DotVVM.Framework.Controls;
using DotVVM.Framework.Runtime;
using DotVVM.Framework.Storage;
using DotVVM.Framework.ViewModel.Serialization;
using Microsoft.AspNet.WebUtilities;
using Microsoft.Extensions.DependencyInjection;
Expand Down Expand Up @@ -176,7 +176,7 @@ private async Task SaveFiles(IHttpContext context, Group boundary, List<Uploaded
/// </summary>
private async Task<UploadedFile> StoreFile(IHttpContext context, MultipartSection section, IUploadedFileStorage fileStore)
{
var fileId = await fileStore.StoreFile(section.Body);
var fileId = await fileStore.StoreFileAsync(section.Body);
var fileNameGroup = Regex.Match(section.ContentDisposition, @"filename=""?(?<fileName>[^\""]*)", RegexOptions.IgnoreCase).Groups["fileName"];
var fileName = fileNameGroup.Success ? fileNameGroup.Value : string.Empty;
var mimeType = section.ContentType ?? string.Empty;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using DotVVM.Framework.Storage;
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
using DotVVM.Core.Storage;
#if DotNetCore
using Microsoft.Net.Http.Headers;
#else
Expand All @@ -30,27 +30,27 @@ public async Task<bool> Handle(IDotvvmRequestContext request)

private async Task RenderReturnedFile(IHttpContext context, IReturnedFileStorage returnedFileStorage)
{
ReturnedFileMetadata metadata;

var id = Guid.Parse(context.Request.Query["id"]);
using (var stream = returnedFileStorage.GetFile(id, out metadata))

var returnedFile = await returnedFileStorage.GetFileAsync(id);
using (var stream = returnedFile.Stream)
{
#if DotNetCore
var contentDispositionValue = new ContentDispositionHeaderValue(metadata.AttachmentDispositionType);
contentDispositionValue.SetHttpFileName(metadata.FileName);
var contentDispositionValue = new ContentDispositionHeaderValue(returnedFile.Metadata.AttachmentDispositionType);
contentDispositionValue.SetHttpFileName(returnedFile.Metadata.FileName);
context.Response.Headers[HeaderNames.ContentDisposition] = contentDispositionValue.ToString();
#else
var contentDispositionValue = new ContentDispositionHeaderValue(metadata.AttachmentDispositionType)
var contentDispositionValue = new ContentDispositionHeaderValue(returnedFile.Metadata.AttachmentDispositionType)
{
FileName = metadata.FileName,
FileNameStar = metadata.FileName
FileName = returnedFile.Metadata.FileName,
FileNameStar = returnedFile.Metadata.FileName
};
context.Response.Headers["Content-Disposition"] = contentDispositionValue.ToString();
#endif
context.Response.ContentType = metadata.MimeType;
if (metadata.AdditionalHeaders != null)
context.Response.ContentType = returnedFile.Metadata.MimeType;
if (returnedFile.Metadata.AdditionalHeaders != null)
{
foreach (var header in metadata.AdditionalHeaders)
foreach (var header in returnedFile.Metadata.AdditionalHeaders)
{
context.Response.Headers.Add(new KeyValuePair<string, string[]>(header.Key, header.Value));
}
Expand Down
15 changes: 10 additions & 5 deletions src/DotVVM.Framework/Storage/FileSystemReturnedFileStorage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using DotVVM.Core.Storage;
using DotVVM.Framework.Configuration;
using DotVVM.Framework.Utils;
using Newtonsoft.Json;
Expand Down Expand Up @@ -69,7 +70,7 @@ private Guid GenerateFileId()
return SecureGuidGenerator.GenerateGuid();
}

public async Task<Guid> StoreFile(Stream stream, ReturnedFileMetadata metadata)
public async Task<Guid> StoreFileAsync(Stream stream, ReturnedFileMetadata metadata)
{
var id = GenerateFileId();
var dataFilePath = GetDataFilePath(id);
Expand Down Expand Up @@ -99,16 +100,18 @@ private string GetMetadataFilePath(Guid id)
return Path.Combine(TempDirectory, id + ".metadata");
}

public Stream GetFile(Guid id, out ReturnedFileMetadata metadata)
public Task<ReturnedFile> GetFileAsync(Guid id)
{
var metadataJson = File.ReadAllText(GetMetadataFilePath(id), Encoding.UTF8);
var settings = DefaultSerializerSettingsProvider.Instance.Settings;
metadata = JsonConvert.DeserializeObject<ReturnedFileMetadata>(metadataJson, settings);

return new FileStream(GetDataFilePath(id), FileMode.Open);
var stream = new FileStream(GetDataFilePath(id), FileMode.Open);
var metadata = JsonConvert.DeserializeObject<ReturnedFileMetadata>(metadataJson, settings);

return Task.FromResult(new ReturnedFile(stream, metadata));
}

public void DeleteFile(Guid id)
public Task DeleteFileAsync(Guid id)
{
try
{
Expand All @@ -125,6 +128,8 @@ public void DeleteFile(Guid id)
catch (IOException)
{
}

return TaskUtils.GetCompletedTask();
}

public void DeleteOldFiles(DateTime maxCreatedDate)
Expand Down
13 changes: 8 additions & 5 deletions src/DotVVM.Framework/Storage/FileSystemUploadedFileStorage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using DotVVM.Core.Storage;
using DotVVM.Framework.Utils;

namespace DotVVM.Framework.Storage
Expand Down Expand Up @@ -37,7 +38,7 @@ public FileSystemUploadedFileStorage(string tempDirectory, TimeSpan autoDeleteIn
/// <summary>
/// Stores uploaded file and returns its unique id.
/// </summary>
public async Task<Guid> StoreFile(Stream stream)
public async Task<Guid> StoreFileAsync(Stream stream)
{
var id = SecureGuidGenerator.GenerateGuid();
using (var fs = new FileStream(GetFileName(id), FileMode.OpenOrCreate, FileAccess.Write))
Expand All @@ -50,7 +51,7 @@ public async Task<Guid> StoreFile(Stream stream)
/// <summary>
/// Deletes the uploaded file.
/// </summary>
public void DeleteFile(Guid fileId)
public Task DeleteFileAsync(Guid fileId)
{
try
{
Expand All @@ -59,14 +60,16 @@ public void DeleteFile(Guid fileId)
catch (IOException)
{
}
return TaskUtils.GetCompletedTask();
}

/// <summary>
/// Gets the file with the specified id.
/// </summary>
public Stream GetFile(Guid fileId)
public Task<Stream> GetFileAsync(Guid fileId)
{
return new FileStream(GetFileName(fileId), FileMode.Open, FileAccess.Read);
var stream = new FileStream(GetFileName(fileId), FileMode.Open, FileAccess.Read);
return Task.FromResult<Stream>(stream);
}

/// <summary>
Expand Down Expand Up @@ -107,4 +110,4 @@ public void Dispose()
}
}
}
}
}

0 comments on commit 6bdbc01

Please sign in to comment.