Skip to content
This repository was archived by the owner on Nov 20, 2018. It is now read-only.

Commit 4986137

Browse files
committed
Use filename* for files in multipart forms when available #651
1 parent 3c0c021 commit 4986137

File tree

2 files changed

+61
-1
lines changed

2 files changed

+61
-1
lines changed

src/Microsoft.AspNetCore.Http/Features/FormFeature.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,9 @@ private async Task<IFormCollection> InnerReadFormAsync(CancellationToken cancell
181181
await section.Body.DrainAsync(cancellationToken);
182182

183183
var name = HeaderUtilities.RemoveQuotes(contentDisposition.Name) ?? string.Empty;
184-
var fileName = HeaderUtilities.RemoveQuotes(contentDisposition.FileName) ?? string.Empty;
184+
var fileName = HeaderUtilities.RemoveQuotes(contentDisposition.FileNameStar) ??
185+
HeaderUtilities.RemoveQuotes(contentDisposition.FileName) ??
186+
string.Empty;
185187

186188
FormFile file;
187189
if (section.BaseStreamOffset.HasValue)

test/Microsoft.AspNetCore.Http.Tests/Features/FormFeatureTests.cs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@ public async Task ReadFormAsync_SimpleData_ReturnsParsedFormCollection(bool buff
6363
"Content-Disposition: form-data; name=\"myfile1\"; filename=\"temp.html\"\r\n" +
6464
"Content-Type: text/html\r\n" +
6565
"\r\n" +
66+
"<html><body>Hello World</body></html>\r\n";
67+
68+
private const string MultipartFormEncodedFilename = "--WebKitFormBoundary5pDRpGheQXaM8k3T\r\n" +
69+
"Content-Disposition: form-data; name=\"myfile1\"; filename=\"temp.html\"; filename*=utf-8\'\'t%c3%a9mp.html\r\n" +
70+
"Content-Type: text/html\r\n" +
71+
"\r\n" +
6672
"<html><body>Hello World</body></html>\r\n";
6773

6874
private const string MultipartFormWithField =
@@ -78,6 +84,10 @@ public async Task ReadFormAsync_SimpleData_ReturnsParsedFormCollection(bool buff
7884
MultipartFormFile +
7985
MultipartFormEnd;
8086

87+
private const string MultipartFormWithEncodedFilename =
88+
MultipartFormEncodedFilename +
89+
MultipartFormEnd;
90+
8191
[Theory]
8292
[InlineData(true)]
8393
[InlineData(false)]
@@ -198,6 +208,54 @@ public async Task ReadFormAsync_MultipartWithFile_ReturnsParsedFormCollection(bo
198208
await responseFeature.CompleteAsync();
199209
}
200210

211+
[Theory]
212+
[InlineData(true)]
213+
[InlineData(false)]
214+
public async Task ReadFormAsync_MultipartWithEncodedFilename_ReturnsParsedFormCollection(bool bufferRequest)
215+
{
216+
var formContent = Encoding.UTF8.GetBytes(MultipartFormWithEncodedFilename);
217+
var context = new DefaultHttpContext();
218+
var responseFeature = new FakeResponseFeature();
219+
context.Features.Set<IHttpResponseFeature>(responseFeature);
220+
context.Request.ContentType = MultipartContentType;
221+
context.Request.Body = new NonSeekableReadStream(formContent);
222+
223+
IFormFeature formFeature = new FormFeature(context.Request, new FormOptions() { BufferBody = bufferRequest });
224+
context.Features.Set<IFormFeature>(formFeature);
225+
226+
var formCollection = await context.Request.ReadFormAsync();
227+
228+
Assert.NotNull(formCollection);
229+
230+
// Cached
231+
formFeature = context.Features.Get<IFormFeature>();
232+
Assert.NotNull(formFeature);
233+
Assert.NotNull(formFeature.Form);
234+
Assert.Same(formFeature.Form, formCollection);
235+
Assert.Same(formCollection, context.Request.Form);
236+
237+
// Content
238+
Assert.Equal(0, formCollection.Count);
239+
240+
Assert.NotNull(formCollection.Files);
241+
Assert.Equal(1, formCollection.Files.Count);
242+
243+
var file = formCollection.Files["myfile1"];
244+
Assert.Equal("myfile1", file.Name);
245+
Assert.Equal("t\u00e9mp.html", file.FileName);
246+
Assert.Equal("text/html", file.ContentType);
247+
Assert.Equal(@"form-data; name=""myfile1""; filename=""temp.html""; filename*=utf-8''t%c3%a9mp.html", file.ContentDisposition);
248+
var body = file.OpenReadStream();
249+
using (var reader = new StreamReader(body))
250+
{
251+
Assert.True(body.CanSeek);
252+
var content = reader.ReadToEnd();
253+
Assert.Equal(content, "<html><body>Hello World</body></html>");
254+
}
255+
256+
await responseFeature.CompleteAsync();
257+
}
258+
201259
[Theory]
202260
[InlineData(true)]
203261
[InlineData(false)]

0 commit comments

Comments
 (0)