Use ContentDisposition class to parse and create content disposition
This commit is contained in:
parent
bb2fa55d0e
commit
eb88e40efa
|
|
@ -1,5 +1,6 @@
|
|||
using System.IO.Compression;
|
||||
using System.Net;
|
||||
using System.Net.Http.Headers;
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Http.Contracts;
|
||||
using Elsa.Http.Models;
|
||||
|
|
@ -101,7 +102,7 @@ public class WriteFileHttpResponse : Activity
|
|||
filename = !string.IsNullOrWhiteSpace(filename) ? filename : !string.IsNullOrWhiteSpace(downloadable.Filename) ? downloadable.Filename : "file.bin";
|
||||
contentType = !string.IsNullOrWhiteSpace(contentType) ? contentType : !string.IsNullOrWhiteSpace(downloadable.ContentType) ? downloadable.ContentType : GetContentType(context, filename);
|
||||
response.ContentType = contentType;
|
||||
response.Headers.Add("Content-Disposition", $"attachment; filename=\"{filename}\"");
|
||||
response.Headers.Add("Content-Disposition", CreateContentDisposition(filename));
|
||||
await downloadable.Stream.CopyToAsync(response.Body);
|
||||
}
|
||||
|
||||
|
|
@ -130,7 +131,7 @@ public class WriteFileHttpResponse : Activity
|
|||
|
||||
memoryStream.Position = 0;
|
||||
response.ContentType = contentType;
|
||||
response.Headers.Add("Content-Disposition", $"attachment; filename=\"{filename}\"");
|
||||
response.Headers.Add("Content-Disposition", CreateContentDisposition(filename));
|
||||
await memoryStream.CopyToAsync(response.Body);
|
||||
}
|
||||
|
||||
|
|
@ -145,8 +146,18 @@ public class WriteFileHttpResponse : Activity
|
|||
|
||||
private string GetContentType(ActivityExecutionContext context, string filename)
|
||||
{
|
||||
var provider = context.GetService<IContentTypeProvider>() ?? new FileExtensionContentTypeProvider();
|
||||
return provider.TryGetContentType(filename, out var contentType) ? contentType : "application/octet-stream";
|
||||
var provider = context.GetRequiredService<IContentTypeProvider>();
|
||||
return provider.TryGetContentType(filename, out var contentType) ? contentType : System.Net.Mime.MediaTypeNames.Application.Octet;
|
||||
}
|
||||
|
||||
private static string CreateContentDisposition(string filename)
|
||||
{
|
||||
var contentDisposition = new System.Net.Mime.ContentDisposition
|
||||
{
|
||||
FileName = filename
|
||||
};
|
||||
|
||||
return contentDisposition.ToString();
|
||||
}
|
||||
|
||||
private async ValueTask OnResumeAsync(ActivityExecutionContext context)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ using Elsa.Http.Abstractions;
|
|||
using Elsa.Http.Contexts;
|
||||
using Elsa.Http.Contracts;
|
||||
using Elsa.Http.Models;
|
||||
using Microsoft.AspNetCore.StaticFiles;
|
||||
|
||||
namespace Elsa.Http.DownloadableProviders;
|
||||
|
||||
|
|
@ -12,11 +13,13 @@ namespace Elsa.Http.DownloadableProviders;
|
|||
public class UrlDownloadableProvider : DownloadableProviderBase
|
||||
{
|
||||
private readonly IFileDownloader _fileDownloader;
|
||||
private readonly IContentTypeProvider _contentTypeProvider;
|
||||
|
||||
/// <inheritdoc />
|
||||
public UrlDownloadableProvider(IFileDownloader fileDownloader)
|
||||
public UrlDownloadableProvider(IFileDownloader fileDownloader, IContentTypeProvider contentTypeProvider)
|
||||
{
|
||||
_fileDownloader = fileDownloader;
|
||||
_contentTypeProvider = contentTypeProvider;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
@ -28,11 +31,11 @@ public class UrlDownloadableProvider : DownloadableProviderBase
|
|||
var url = context.Content is string s ? new Uri(s) : (Uri)context.Content;
|
||||
var cancellationToken = context.CancellationToken;
|
||||
var response = await _fileDownloader.DownloadAsync(url, cancellationToken);
|
||||
var fileName = GetFilename(response) ?? url.Segments.Last();
|
||||
var filename = GetFilename(response) ?? url.Segments.Last();
|
||||
var stream = await response.Content.ReadAsStreamAsync(cancellationToken);
|
||||
var contentType = response.Content.Headers.ContentType?.MediaType ?? "application/octet-stream";
|
||||
var contentType = response.Content.Headers.ContentType?.MediaType ?? GetContentType(filename);
|
||||
|
||||
return new Downloadable(stream, fileName, contentType);
|
||||
return new Downloadable(stream, filename, contentType);
|
||||
}
|
||||
|
||||
private static string? GetFilename(HttpResponseMessage response)
|
||||
|
|
@ -40,10 +43,14 @@ public class UrlDownloadableProvider : DownloadableProviderBase
|
|||
if (!response.Content.Headers.TryGetValues("Content-Disposition", out var values))
|
||||
return null;
|
||||
|
||||
var contentDisposition = string.Join("", values);
|
||||
var match = Regex.Match(contentDisposition, """filename="?(?<filename>[^";]*)"?""");
|
||||
|
||||
return match.Success ? match.Groups["filename"].Value : null;
|
||||
var contentDispositionString = string.Join("", values);
|
||||
var contentDisposition = new System.Net.Mime.ContentDisposition(contentDispositionString);
|
||||
return contentDisposition.FileName;
|
||||
}
|
||||
|
||||
private string GetContentType(string filename)
|
||||
{
|
||||
return _contentTypeProvider.TryGetContentType(filename, out var contentType) ? contentType : System.Net.Mime.MediaTypeNames.Application.Octet;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -22,6 +22,7 @@ using Elsa.Workflows.Management.Requests;
|
|||
using Elsa.Workflows.Management.Responses;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.AspNetCore.StaticFiles;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Elsa.Http.Features;
|
||||
|
|
@ -53,6 +54,11 @@ public class HttpFeature : FeatureBase
|
|||
/// A delegate that is invoked when an HTTP workflow faults.
|
||||
/// </summary>
|
||||
public Func<IServiceProvider, IHttpEndpointWorkflowFaultHandler> HttpEndpointWorkflowFaultHandler { get; set; } = sp => sp.GetRequiredService<DefaultHttpEndpointWorkflowFaultHandler>();
|
||||
|
||||
/// <summary>
|
||||
/// A delegate to configure the <see cref="IContentTypeProvider"/>.
|
||||
/// </summary>
|
||||
public Func<IServiceProvider, IContentTypeProvider> ContentTypeProvider { get; set; } = _ => new FileExtensionContentTypeProvider();
|
||||
|
||||
/// <summary>
|
||||
/// A delegate to configure the <see cref="HttpClient"/> used when by the <see cref="FlowSendHttpRequest"/> activity.
|
||||
|
|
@ -128,6 +134,7 @@ public class HttpFeature : FeatureBase
|
|||
.AddSingleton<IAbsoluteUrlProvider, DefaultAbsoluteUrlProvider>()
|
||||
.AddSingleton<IHttpBookmarkProcessor, HttpBookmarkProcessor>()
|
||||
.AddSingleton<IRouteTableUpdater, DefaultRouteTableUpdater>()
|
||||
.AddSingleton(ContentTypeProvider)
|
||||
.AddNotificationHandlersFrom<UpdateRouteTable>()
|
||||
.AddHttpContextAccessor()
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue