From a8035679b45b2702fdb444ddd87e844301c529ad Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Tue, 18 Oct 2022 18:46:57 +0800 Subject: [PATCH 1/5] Fix download file Chinese name garbled problem --- .../Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs index 8c0ab4f538..4c5e1523ea 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Threading; @@ -91,8 +92,9 @@ public class ClientProxyBase : ITransientDependency * it before we finish doing our work with the stream */ return (T)(object)new RemoteStreamContent( await responseContent.ReadAsStreamAsync(), + WebUtility.UrlDecode( responseContent.Headers?.ContentDisposition?.FileNameStar ?? - RemoveQuotes(responseContent.Headers?.ContentDisposition?.FileName).ToString(), + RemoveQuotes(responseContent.Headers?.ContentDisposition?.FileName).ToString()), responseContent.Headers?.ContentType?.ToString(), responseContent.Headers?.ContentLength); } From 241b57b36fcb16e07491260956855723a6702121 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Wed, 19 Oct 2022 10:33:36 +0800 Subject: [PATCH 2/5] Improve --- .../ContentFormatters/RemoteStreamContentOutputFormatter.cs | 4 ++-- .../Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs | 4 +--- 2 files changed, 3 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 5c5e7ed6c0..5f2ff67c6e 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 @@ -27,10 +27,10 @@ public class RemoteStreamContentOutputFormatter : OutputFormatter context.HttpContext.Response.ContentType = remoteStream.ContentType; context.HttpContext.Response.ContentLength = remoteStream.ContentLength; - if (!remoteStream.FileName.IsNullOrWhiteSpace()) + if (!remoteStream.FileName.IsNullOrWhiteSpace() && !context.HttpContext.Response.Headers.ContainsKey(HeaderNames.ContentDisposition)) { var contentDisposition = new ContentDispositionHeaderValue("attachment"); - contentDisposition.SetHttpFileName(remoteStream.FileName); + contentDisposition.SetMimeFileName(remoteStream.FileName); context.HttpContext.Response.Headers[HeaderNames.ContentDisposition] = contentDisposition.ToString(); } diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs index 4c5e1523ea..8c0ab4f538 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; -using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Threading; @@ -92,9 +91,8 @@ public class ClientProxyBase : ITransientDependency * it before we finish doing our work with the stream */ return (T)(object)new RemoteStreamContent( await responseContent.ReadAsStreamAsync(), - WebUtility.UrlDecode( responseContent.Headers?.ContentDisposition?.FileNameStar ?? - RemoveQuotes(responseContent.Headers?.ContentDisposition?.FileName).ToString()), + RemoveQuotes(responseContent.Headers?.ContentDisposition?.FileName).ToString(), responseContent.Headers?.ContentType?.ToString(), responseContent.Headers?.ContentLength); } From 88b64b4160dcf4e4ec953b18115bffc58343c71b Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Wed, 19 Oct 2022 10:40:42 +0800 Subject: [PATCH 3/5] Improve --- .../Mvc/ContentFormatters/RemoteStreamContentOutputFormatter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 5f2ff67c6e..e41616617d 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 @@ -30,7 +30,7 @@ public class RemoteStreamContentOutputFormatter : OutputFormatter if (!remoteStream.FileName.IsNullOrWhiteSpace() && !context.HttpContext.Response.Headers.ContainsKey(HeaderNames.ContentDisposition)) { var contentDisposition = new ContentDispositionHeaderValue("attachment"); - contentDisposition.SetMimeFileName(remoteStream.FileName); + contentDisposition.SetHttpFileName(remoteStream.FileName); context.HttpContext.Response.Headers[HeaderNames.ContentDisposition] = contentDisposition.ToString(); } From f48ae4998127617f427ea677476a50320158ca8c Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Wed, 19 Oct 2022 11:07:19 +0800 Subject: [PATCH 4/5] Add unit tests --- .../RemoteStreamContentTestController.cs | 11 +++++++++++ .../RemoteStreamContentTestController_Tests.cs | 10 ++++++++++ 2 files changed, 21 insertions(+) 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 42c84a8037..f8568323fa 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 @@ -19,6 +19,17 @@ public class RemoteStreamContentTestController : AbpController memoryStream.Position = 0; return new RemoteStreamContent(memoryStream, "download.rtf", "application/rtf"); } + + [HttpGet] + [Route("Download-With-Custom-Content-Disposition")] + public async Task Download_With_Custom_Content_Disposition_Async() + { + var memoryStream = new MemoryStream(); + await memoryStream.WriteAsync(Encoding.UTF8.GetBytes("DownloadAsync")); + memoryStream.Position = 0; + Response.Headers.Add("Content-Disposition", "attachment; filename=myDownload.rtf"); + return new RemoteStreamContent(memoryStream, "download.rtf", "application/rtf"); + } [HttpPost] [Route("Upload")] 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 1a60ab9d6b..af3b155f55 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 @@ -19,6 +19,16 @@ public class RemoteStreamContentTestController_Tests : AspNetCoreMvcTestBase result.Content.Headers.ContentLength.ShouldBe("DownloadAsync".Length); (await result.Content.ReadAsStringAsync()).ShouldBe("DownloadAsync"); } + + [Fact] + public async Task Download_With_Custom_Content_Disposition_Async() + { + var result = await GetResponseAsync("/api/remote-stream-content-test/download-with-custom-content-disposition"); + result.Content.Headers.ContentType?.ToString().ShouldBe("application/rtf"); + result.Content.Headers.ContentDisposition?.FileName.ShouldBe("myDownload.rtf"); + result.Content.Headers.ContentLength.ShouldBe("DownloadAsync".Length); + (await result.Content.ReadAsStringAsync()).ShouldBe("DownloadAsync"); + } [Fact] public async Task UploadAsync() From 31e5a079d79689266bc640f3fb7d961a024e6e05 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Wed, 19 Oct 2022 11:12:53 +0800 Subject: [PATCH 5/5] Add unit tests --- .../RemoteStreamContentTestController.cs | 10 ++++++++++ .../RemoteStreamContentTestController_Tests.cs | 13 ++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) 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 f8568323fa..5efebb4603 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 @@ -30,6 +30,16 @@ public class RemoteStreamContentTestController : AbpController Response.Headers.Add("Content-Disposition", "attachment; filename=myDownload.rtf"); return new RemoteStreamContent(memoryStream, "download.rtf", "application/rtf"); } + + [HttpGet] + [Route("Download_With_Chinese_File_Name")] + public async Task Download_With_Chinese_File_Name_Async() + { + var memoryStream = new MemoryStream(); + await memoryStream.WriteAsync(Encoding.UTF8.GetBytes("DownloadAsync")); + memoryStream.Position = 0; + return new RemoteStreamContent(memoryStream, "下载文件.rtf", "application/rtf"); + } [HttpPost] [Route("Upload")] 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 af3b155f55..321c0099f1 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 @@ -3,6 +3,7 @@ using System.Net.Http; using System.Net.Http.Headers; using System.Text; using System.Threading.Tasks; +using System.Web; using Shouldly; using Xunit; @@ -20,7 +21,7 @@ public class RemoteStreamContentTestController_Tests : AspNetCoreMvcTestBase (await result.Content.ReadAsStringAsync()).ShouldBe("DownloadAsync"); } - [Fact] + [Fact] public async Task Download_With_Custom_Content_Disposition_Async() { var result = await GetResponseAsync("/api/remote-stream-content-test/download-with-custom-content-disposition"); @@ -29,6 +30,16 @@ public class RemoteStreamContentTestController_Tests : AspNetCoreMvcTestBase result.Content.Headers.ContentLength.ShouldBe("DownloadAsync".Length); (await result.Content.ReadAsStringAsync()).ShouldBe("DownloadAsync"); } + + [Fact] + public async Task Download_With_Chinese_File_Name_Async() + { + var result = await GetResponseAsync("/api/remote-stream-content-test/download_with_chinese_file_name"); + result.Content.Headers.ContentType?.ToString().ShouldBe("application/rtf"); + result.Content.Headers.ContentDisposition?.FileNameStar.ShouldBe("下载文件.rtf"); + result.Content.Headers.ContentLength.ShouldBe("DownloadAsync".Length); + (await result.Content.ReadAsStringAsync()).ShouldBe("DownloadAsync"); + } [Fact] public async Task UploadAsync()