From 15743d178516c79dec4be018f4d1d7515b53d923 Mon Sep 17 00:00:00 2001 From: Jadyn Date: Thu, 24 Jun 2021 22:40:11 +0800 Subject: [PATCH 1/6] Add FileName for RemoteStreamContent --- .../AbpRemoteStreamContentModelBinder.cs | 3 +- .../RemoteStreamContentOutputFormatter.cs | 6 +++ .../Volo/Abp/Content/IRemoteStreamContent.cs | 2 + .../Volo/Abp/Content/RemoteStreamContent.cs | 7 ++++ .../DynamicHttpProxyInterceptor.cs | 3 +- .../DynamicProxying/RequestPayloadBuilder.cs | 5 ++- .../RemoteStreamContentTestController.cs | 4 +- ...RemoteStreamContentTestController_Tests.cs | 5 ++- .../PersonAppServiceClientProxy_Tests.cs | 41 ++++++++++--------- .../TestApp/Application/PeopleAppService.cs | 12 +++--- 10 files changed, 54 insertions(+), 34 deletions(-) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/AbpRemoteStreamContentModelBinder.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/AbpRemoteStreamContentModelBinder.cs index da58641d7e..30161b77b1 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/AbpRemoteStreamContentModelBinder.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/AbpRemoteStreamContentModelBinder.cs @@ -110,7 +110,8 @@ namespace Volo.Abp.AspNetCore.Mvc.ContentFormatters { postedFiles.Add(new RemoteStreamContent(file.OpenReadStream()) { - ContentType = file.ContentType + ContentType = file.ContentType, + FileName = file.FileName }); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentOutputFormatter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentOutputFormatter.cs index 188306227a..00ae71fbd2 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentOutputFormatter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentOutputFormatter.cs @@ -26,6 +26,12 @@ namespace Volo.Abp.AspNetCore.Mvc.ContentFormatters { context.HttpContext.Response.ContentType = remoteStream.ContentType; + if (!remoteStream.FileName.IsNullOrWhiteSpace()) + { + //https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition#syntax + context.HttpContext.Response.Headers.Add("Content-Disposition", $"attachment; filename=\"{remoteStream.FileName}\""); + } + using (var stream = remoteStream.GetStream()) { if (stream.CanSeek) diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Content/IRemoteStreamContent.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Content/IRemoteStreamContent.cs index bca259d422..0145305f09 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Content/IRemoteStreamContent.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Content/IRemoteStreamContent.cs @@ -8,6 +8,8 @@ namespace Volo.Abp.Content long? ContentLength { get; } + string FileName { get; } + Stream GetStream(); } } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Content/RemoteStreamContent.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Content/RemoteStreamContent.cs index f217101cea..613697dc5b 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Content/RemoteStreamContent.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Content/RemoteStreamContent.cs @@ -11,10 +11,17 @@ namespace Volo.Abp.Content _stream = stream; } + public RemoteStreamContent(Stream stream, string fileName): this(stream) + { + FileName = fileName; + } + public virtual string ContentType { get; set; } public virtual long? ContentLength => _stream.Length; + public virtual string FileName { get; set; } + public virtual Stream GetStream() { return _stream; diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs index 7914068bca..f9712e699d 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs @@ -114,7 +114,8 @@ namespace Volo.Abp.Http.Client.DynamicProxying * it before we finish doing our work with the stream */ return (T)(object)new RemoteStreamContent(await responseContent.ReadAsStreamAsync()) { - ContentType = responseContent.Headers.ContentType?.ToString() + ContentType = responseContent.Headers.ContentType?.ToString(), + FileName = responseContent.Headers?.ContentDisposition?.FileName?.RemovePreFix("\"")?.RemovePostFix("\"") }; } diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/RequestPayloadBuilder.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/RequestPayloadBuilder.cs index 1096fa971e..b121852c2c 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/RequestPayloadBuilder.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/RequestPayloadBuilder.cs @@ -90,8 +90,9 @@ namespace Volo.Abp.Http.Client.DynamicProxying if (!remoteStreamContent.ContentType.IsNullOrWhiteSpace()) { streamContent.Headers.ContentType = new MediaTypeHeaderValue(remoteStreamContent.ContentType); + } - formData.Add(streamContent, parameter.Name, parameter.Name); + formData.Add(streamContent, parameter.Name, remoteStreamContent.FileName ?? parameter.Name); } else if (value is IEnumerable remoteStreamContents) { @@ -107,7 +108,7 @@ namespace Volo.Abp.Http.Client.DynamicProxying { streamContent.Headers.ContentType = new MediaTypeHeaderValue(content.ContentType); } - formData.Add(streamContent, parameter.Name, parameter.Name); + formData.Add(streamContent, parameter.Name, content.FileName ?? parameter.Name); } } else diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentTestController.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentTestController.cs index e74c9d52e8..7743e575ed 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentTestController.cs +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentTestController.cs @@ -17,7 +17,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ContentFormatters var memoryStream = new MemoryStream(); await memoryStream.WriteAsync(Encoding.UTF8.GetBytes("DownloadAsync")); - return new RemoteStreamContent(memoryStream) + return new RemoteStreamContent(memoryStream, "download.rtf") { ContentType = "application/rtf" }; @@ -29,7 +29,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ContentFormatters { using (var reader = new StreamReader(file.GetStream())) { - return await reader.ReadToEndAsync() + ":" + file.ContentType; + return await reader.ReadToEndAsync() + ":" + file.ContentType + ":" + file.FileName; } } } diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentTestController_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentTestController_Tests.cs index 12745da732..4bc03593ff 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentTestController_Tests.cs +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentTestController_Tests.cs @@ -15,6 +15,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ContentFormatters { var result = await GetResponseAsync("/api/remote-stream-content-test/download"); result.Content.Headers.ContentType?.ToString().ShouldBe("application/rtf"); + result.Content.Headers.ContentDisposition?.FileName.ShouldBe("\"download.rtf\""); (await result.Content.ReadAsStringAsync()).ShouldBe("DownloadAsync"); } @@ -30,11 +31,11 @@ namespace Volo.Abp.AspNetCore.Mvc.ContentFormatters var streamContent = new StreamContent(memoryStream); streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/rtf"); - requestMessage.Content = new MultipartFormDataContent {{streamContent, "file", "file"}}; + requestMessage.Content = new MultipartFormDataContent {{streamContent, "file", "upload.rtf"}}; var response = await Client.SendAsync(requestMessage); - (await response.Content.ReadAsStringAsync()).ShouldBe("UploadAsync:application/rtf"); + (await response.Content.ReadAsStringAsync()).ShouldBe("UploadAsync:application/rtf:upload.rtf"); } } } diff --git a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/PersonAppServiceClientProxy_Tests.cs b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/PersonAppServiceClientProxy_Tests.cs index 026373d568..1b36bb50c4 100644 --- a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/PersonAppServiceClientProxy_Tests.cs +++ b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/PersonAppServiceClientProxy_Tests.cs @@ -49,7 +49,7 @@ namespace Volo.Abp.Http.DynamicProxying { var people = await _peopleAppService.GetListAsync(new PagedAndSortedResultRequestDto()); people.TotalCount.ShouldBeGreaterThan(0); - people.Items.Count.ShouldBe((int) people.TotalCount); + people.Items.Count.ShouldBe((int)people.TotalCount); } [Fact] @@ -62,7 +62,7 @@ namespace Volo.Abp.Http.DynamicProxying { id1, id2 - }, new[] {"name1", "name2"}); + }, new[] { "name1", "name2" }); @params.ShouldContain(id1.ToString("N")); @params.ShouldContain(id2.ToString("N")); @@ -87,10 +87,10 @@ namespace Volo.Abp.Http.DynamicProxying var uniquePersonName = Guid.NewGuid().ToString(); var person = await _peopleAppService.CreateAsync(new PersonDto - { - Name = uniquePersonName, - Age = 42 - } + { + Name = uniquePersonName, + Age = 42 + } ); person.ShouldNotBeNull(); @@ -108,9 +108,9 @@ namespace Volo.Abp.Http.DynamicProxying await Assert.ThrowsAsync(async () => { var person = await _peopleAppService.CreateAsync(new PersonDto - { - Age = 42 - } + { + Age = 42 + } ); }); } @@ -180,6 +180,7 @@ namespace Volo.Abp.Http.DynamicProxying { var result = await _peopleAppService.DownloadAsync(); + result.FileName.ShouldBe("download.rtf"); result.ContentType.ShouldBe("application/rtf"); using (var reader = new StreamReader(result.GetStream())) { @@ -194,11 +195,11 @@ namespace Volo.Abp.Http.DynamicProxying var memoryStream = new MemoryStream(); await memoryStream.WriteAsync(Encoding.UTF8.GetBytes("UploadAsync")); memoryStream.Position = 0; - var result = await _peopleAppService.UploadAsync(new RemoteStreamContent(memoryStream) + var result = await _peopleAppService.UploadAsync(new RemoteStreamContent(memoryStream, "upload.rtf") { ContentType = "application/rtf" }); - result.ShouldBe("UploadAsync:application/rtf"); + result.ShouldBe("UploadAsync:application/rtf:upload.rtf"); } [Fact] @@ -214,17 +215,17 @@ namespace Volo.Abp.Http.DynamicProxying var result = await _peopleAppService.UploadMultipleAsync(new List() { - new RemoteStreamContent(memoryStream) + new RemoteStreamContent(memoryStream,"File1.rtf") { ContentType = "application/rtf" }, - new RemoteStreamContent(memoryStream2) + new RemoteStreamContent(memoryStream2,"File2.rtf") { ContentType = "application/rtf2" } }); - result.ShouldBe("File1:application/rtfFile2:application/rtf2"); + result.ShouldBe("File1:application/rtf:File1.rtfFile2:application/rtf2:File2.rtf"); } [Fact] @@ -236,12 +237,12 @@ namespace Volo.Abp.Http.DynamicProxying var result = await _peopleAppService.CreateFileAsync(new CreateFileInput() { Name = "123.rtf", - Content = new RemoteStreamContent(memoryStream) + Content = new RemoteStreamContent(memoryStream, "create.rtf") { ContentType = "application/rtf" } }); - result.ShouldBe("123.rtf:CreateFileAsync:application/rtf"); + result.ShouldBe("123.rtf:CreateFileAsync:application/rtf:create.rtf"); } [Fact] @@ -264,12 +265,12 @@ namespace Volo.Abp.Http.DynamicProxying Name = "123.rtf", Contents = new List() { - new RemoteStreamContent(memoryStream) + new RemoteStreamContent(memoryStream,"1-1.rtf") { ContentType = "application/rtf" }, - new RemoteStreamContent(memoryStream2) + new RemoteStreamContent(memoryStream2,"1-2.rtf") { ContentType = "application/rtf2" } @@ -277,13 +278,13 @@ namespace Volo.Abp.Http.DynamicProxying Inner = new CreateFileInput() { Name = "789.rtf", - Content = new RemoteStreamContent(memoryStream3) + Content = new RemoteStreamContent(memoryStream3, "i-789.rtf") { ContentType = "application/rtf3" } } }); - result.ShouldBe("123.rtf:File1:application/rtf123.rtf:File2:application/rtf2789.rtf:File3:application/rtf3"); + result.ShouldBe("123.rtf:File1:application/rtf:1-1.rtf123.rtf:File2:application/rtf2:1-2.rtf789.rtf:File3:application/rtf3:i-789.rtf"); } } } diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/PeopleAppService.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/PeopleAppService.cs index edd6a3b93f..f3dfef2891 100644 --- a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/PeopleAppService.cs +++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/PeopleAppService.cs @@ -73,7 +73,7 @@ namespace Volo.Abp.TestApp.Application var memoryStream = new MemoryStream(); await memoryStream.WriteAsync(Encoding.UTF8.GetBytes("DownloadAsync")); - return new RemoteStreamContent(memoryStream) + return new RemoteStreamContent(memoryStream, "download.rtf") { ContentType = "application/rtf" }; @@ -83,7 +83,7 @@ namespace Volo.Abp.TestApp.Application { using (var reader = new StreamReader(streamContent.GetStream())) { - return await reader.ReadToEndAsync() + ":" + streamContent.ContentType; + return await reader.ReadToEndAsync() + ":" + streamContent.ContentType + ":" + streamContent.FileName; } } @@ -94,7 +94,7 @@ namespace Volo.Abp.TestApp.Application { using (var reader = new StreamReader(content.GetStream())) { - str += await reader.ReadToEndAsync() + ":" + content.ContentType; + str += await reader.ReadToEndAsync() + ":" + content.ContentType + ":" + content.FileName; } } @@ -105,7 +105,7 @@ namespace Volo.Abp.TestApp.Application { using (var reader = new StreamReader(input.Content.GetStream())) { - return input.Name + ":" + await reader.ReadToEndAsync() + ":" + input.Content.ContentType; + return input.Name + ":" + await reader.ReadToEndAsync() + ":" + input.Content.ContentType + ":" + input.Content.FileName; } } @@ -116,13 +116,13 @@ namespace Volo.Abp.TestApp.Application { using (var reader = new StreamReader(content.GetStream())) { - str += input.Name + ":" + await reader.ReadToEndAsync() + ":" + content.ContentType; + str += input.Name + ":" + await reader.ReadToEndAsync() + ":" + content.ContentType + ":" + content.FileName; } } using (var reader = new StreamReader(input.Inner.Content.GetStream())) { - str += input.Inner.Name + ":" + await reader.ReadToEndAsync() + ":" + input.Inner.Content.ContentType; + str += input.Inner.Name + ":" + await reader.ReadToEndAsync() + ":" + input.Inner.Content.ContentType + ":" + input.Inner.Content.FileName; } return str; From 534fe8f52245f36bd9a4aeddd6dac19403fef0d2 Mon Sep 17 00:00:00 2001 From: Jadyn Date: Fri, 25 Jun 2021 09:48:27 +0800 Subject: [PATCH 2/6] Use FileNameStar for RemoteStreamContent FileName --- .../RemoteStreamContentOutputFormatter.cs | 2 +- .../DynamicProxying/DynamicHttpProxyInterceptor.cs | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentOutputFormatter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentOutputFormatter.cs index 00ae71fbd2..bf9cdac23f 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentOutputFormatter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentOutputFormatter.cs @@ -29,7 +29,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ContentFormatters if (!remoteStream.FileName.IsNullOrWhiteSpace()) { //https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition#syntax - context.HttpContext.Response.Headers.Add("Content-Disposition", $"attachment; filename=\"{remoteStream.FileName}\""); + context.HttpContext.Response.Headers.Add("Content-Disposition", $"attachment; filename=\"{remoteStream.FileName}\"; filename*=UTF-8''{Uri.EscapeDataString(remoteStream.FileName)}"); } using (var stream = remoteStream.GetStream()) diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs index f9712e699d..57d1d6c68b 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs @@ -57,7 +57,7 @@ namespace Volo.Abp.Http.Client.DynamicProxying ICancellationTokenProvider cancellationTokenProvider, ICorrelationIdProvider correlationIdProvider, IOptions correlationIdOptions, - ICurrentTenant currentTenant, + ICurrentTenant currentTenant, IRemoteServiceConfigurationProvider remoteServiceConfigurationProvider) { CancellationTokenProvider = cancellationTokenProvider; @@ -115,7 +115,8 @@ namespace Volo.Abp.Http.Client.DynamicProxying return (T)(object)new RemoteStreamContent(await responseContent.ReadAsStreamAsync()) { ContentType = responseContent.Headers.ContentType?.ToString(), - FileName = responseContent.Headers?.ContentDisposition?.FileName?.RemovePreFix("\"")?.RemovePostFix("\"") + FileName = responseContent.Headers?.ContentDisposition?.FileNameStar ?? + responseContent.Headers?.ContentDisposition?.FileName?.RemovePreFix("\"")?.RemovePostFix("\"") }; } @@ -278,7 +279,7 @@ namespace Volo.Abp.Http.Client.DynamicProxying throw new AbpRemoteCallException(errorResponse.Error) { - HttpStatusCode = (int) response.StatusCode + HttpStatusCode = (int)response.StatusCode }; } @@ -290,7 +291,7 @@ namespace Volo.Abp.Http.Client.DynamicProxying } ) { - HttpStatusCode = (int) response.StatusCode + HttpStatusCode = (int)response.StatusCode }; } From c69447d73238d86443b86ed9e5f2d64a1fad1457 Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 28 Jun 2021 08:35:14 +0800 Subject: [PATCH 3/6] Use ContentDispositionHeaderValue. --- .../ContentFormatters/RemoteStreamContentOutputFormatter.cs | 5 +++-- .../RemoteStreamContentTestController_Tests.cs | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentOutputFormatter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentOutputFormatter.cs index bf9cdac23f..35e0922f36 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentOutputFormatter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentOutputFormatter.cs @@ -28,8 +28,9 @@ namespace Volo.Abp.AspNetCore.Mvc.ContentFormatters if (!remoteStream.FileName.IsNullOrWhiteSpace()) { - //https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition#syntax - context.HttpContext.Response.Headers.Add("Content-Disposition", $"attachment; filename=\"{remoteStream.FileName}\"; filename*=UTF-8''{Uri.EscapeDataString(remoteStream.FileName)}"); + var contentDisposition = new ContentDispositionHeaderValue("attachment"); + contentDisposition.SetHttpFileName(remoteStream.FileName); + context.HttpContext.Response.Headers[HeaderNames.ContentDisposition] = contentDisposition.ToString(); } using (var stream = remoteStream.GetStream()) diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentTestController_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentTestController_Tests.cs index 4bc03593ff..8f42a5cb37 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentTestController_Tests.cs +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentTestController_Tests.cs @@ -15,7 +15,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ContentFormatters { var result = await GetResponseAsync("/api/remote-stream-content-test/download"); result.Content.Headers.ContentType?.ToString().ShouldBe("application/rtf"); - result.Content.Headers.ContentDisposition?.FileName.ShouldBe("\"download.rtf\""); + result.Content.Headers.ContentDisposition?.FileName.ShouldBe("download.rtf"); (await result.Content.ReadAsStringAsync()).ShouldBe("DownloadAsync"); } From f3c77764a5263065ccdd0dfebe9770ae47499bc7 Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 28 Jun 2021 09:14:22 +0800 Subject: [PATCH 4/6] Add RemoveQuotes method. --- .../DynamicHttpProxyInterceptor.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs index 57d1d6c68b..d10be82096 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; +using Microsoft.Extensions.Primitives; using Volo.Abp.Content; using Volo.Abp.DependencyInjection; using Volo.Abp.DynamicProxy; @@ -115,8 +116,8 @@ namespace Volo.Abp.Http.Client.DynamicProxying return (T)(object)new RemoteStreamContent(await responseContent.ReadAsStreamAsync()) { ContentType = responseContent.Headers.ContentType?.ToString(), - FileName = responseContent.Headers?.ContentDisposition?.FileNameStar ?? - responseContent.Headers?.ContentDisposition?.FileName?.RemovePreFix("\"")?.RemovePostFix("\"") + FileName = responseContent.Headers?.ContentDisposition?.FileNameStar ?? + RemoveQuotes(responseContent.Headers?.ContentDisposition?.FileName).ToString() }; } @@ -295,6 +296,16 @@ namespace Volo.Abp.Http.Client.DynamicProxying }; } + protected virtual StringSegment RemoveQuotes(StringSegment input) + { + if (!StringSegment.IsNullOrEmpty(input) && input.Length >= 2 && input[0] == '"' && input[input.Length - 1] == '"') + { + input = input.Subsegment(1, input.Length - 2); + } + + return input; + } + protected virtual CancellationToken GetCancellationToken() { return CancellationTokenProvider.Token; From 49058c9eec6bd29bb314dae4f37de6f108c5979d Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 28 Jun 2021 09:21:26 +0800 Subject: [PATCH 5/6] Use application/octet-stream as default value of ContentType. --- .../src/Volo.Abp.Core/Volo/Abp/Content/RemoteStreamContent.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Content/RemoteStreamContent.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Content/RemoteStreamContent.cs index 613697dc5b..602c1aec21 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Content/RemoteStreamContent.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Content/RemoteStreamContent.cs @@ -14,6 +14,7 @@ namespace Volo.Abp.Content public RemoteStreamContent(Stream stream, string fileName): this(stream) { FileName = fileName; + ContentType = "application/octet-stream"; } public virtual string ContentType { get; set; } From 8863a4b7fbf0ac00a16c1dced8b0037c82b95d73 Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 28 Jun 2021 09:32:23 +0800 Subject: [PATCH 6/6] Format code. --- .../Volo/Abp/Content/RemoteStreamContent.cs | 5 +++-- .../DynamicProxying/DynamicHttpProxyInterceptor.cs | 4 ++-- .../PersonAppServiceClientProxy_Tests.cs | 10 +++++----- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Content/RemoteStreamContent.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Content/RemoteStreamContent.cs index 602c1aec21..f24b4d83bd 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Content/RemoteStreamContent.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Content/RemoteStreamContent.cs @@ -11,7 +11,8 @@ namespace Volo.Abp.Content _stream = stream; } - public RemoteStreamContent(Stream stream, string fileName): this(stream) + public RemoteStreamContent(Stream stream, string fileName) + : this(stream) { FileName = fileName; ContentType = "application/octet-stream"; @@ -19,7 +20,7 @@ namespace Volo.Abp.Content public virtual string ContentType { get; set; } - public virtual long? ContentLength => _stream.Length; + public virtual long? ContentLength => GetStream().Length; public virtual string FileName { get; set; } diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs index d10be82096..b94a5a339d 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs @@ -280,7 +280,7 @@ namespace Volo.Abp.Http.Client.DynamicProxying throw new AbpRemoteCallException(errorResponse.Error) { - HttpStatusCode = (int)response.StatusCode + HttpStatusCode = (int) response.StatusCode }; } @@ -292,7 +292,7 @@ namespace Volo.Abp.Http.Client.DynamicProxying } ) { - HttpStatusCode = (int)response.StatusCode + HttpStatusCode = (int) response.StatusCode }; } diff --git a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/PersonAppServiceClientProxy_Tests.cs b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/PersonAppServiceClientProxy_Tests.cs index 1b36bb50c4..d92e1ad5d1 100644 --- a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/PersonAppServiceClientProxy_Tests.cs +++ b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/PersonAppServiceClientProxy_Tests.cs @@ -49,7 +49,7 @@ namespace Volo.Abp.Http.DynamicProxying { var people = await _peopleAppService.GetListAsync(new PagedAndSortedResultRequestDto()); people.TotalCount.ShouldBeGreaterThan(0); - people.Items.Count.ShouldBe((int)people.TotalCount); + people.Items.Count.ShouldBe((int) people.TotalCount); } [Fact] @@ -215,12 +215,12 @@ namespace Volo.Abp.Http.DynamicProxying var result = await _peopleAppService.UploadMultipleAsync(new List() { - new RemoteStreamContent(memoryStream,"File1.rtf") + new RemoteStreamContent(memoryStream, "File1.rtf") { ContentType = "application/rtf" }, - new RemoteStreamContent(memoryStream2,"File2.rtf") + new RemoteStreamContent(memoryStream2, "File2.rtf") { ContentType = "application/rtf2" } @@ -265,12 +265,12 @@ namespace Volo.Abp.Http.DynamicProxying Name = "123.rtf", Contents = new List() { - new RemoteStreamContent(memoryStream,"1-1.rtf") + new RemoteStreamContent(memoryStream, "1-1.rtf") { ContentType = "application/rtf" }, - new RemoteStreamContent(memoryStream2,"1-2.rtf") + new RemoteStreamContent(memoryStream2, "1-2.rtf") { ContentType = "application/rtf2" }