Skip to content

Commit 2ba8e69

Browse files
authored
Address non-ASCII filename support for files, audio, etc. (#75)
* allow filename* use in multipart/form-data * remove unwarranted breaking change description * minor: align filename->fileName
1 parent aca1900 commit 2ba8e69

3 files changed

Lines changed: 33 additions & 45 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Release History
22

3+
## 2.0.0-beta.6 (Unreleased)
4+
5+
## Bugs Fixed
6+
7+
- ([#72](https://github.com/openai/openai-dotnet/issues/72)) Fixed `filename` request encoding in operations using `multipart/form-data`, including `files` and `audio`
8+
39
## 2.0.0-beta.5 (2024-06-14)
410

511
## Features Added

src/Utility/MultipartFormDataBinaryContent.cs

Lines changed: 15 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,18 @@ public string ContentType
3434

3535
internal HttpContent HttpContent => _multipartContent;
3636

37-
public void Add(Stream content, string name, string fileName = default, string contentType = null)
37+
public void Add(Stream stream, string name, string fileName = default, string contentType = null)
3838
{
39-
Argument.AssertNotNull(content, nameof(content));
40-
Argument.AssertNotNullOrEmpty(name, nameof(name));
39+
Argument.AssertNotNull(stream, nameof(stream));
4140

42-
Add(new StreamContent(content), name, fileName, contentType);
41+
StreamContent content = new(stream);
42+
if (contentType is not null)
43+
{
44+
content.Headers.ContentType = MediaTypeHeaderValue.Parse(contentType);
45+
}
46+
Add(content, name, fileName);
4347
}
4448

45-
//public void Add(Stream stream, string name, string fileName = default)
46-
//{
47-
// Add(new StreamContent(stream), name, fileName);
48-
//}
49-
5049
public void Add(string content, string name, string fileName = default)
5150
{
5251
Add(new StringContent(content), name, fileName);
@@ -76,48 +75,19 @@ public void Add(BinaryData content, string name, string fileName = default)
7675
Add(new ByteArrayContent(content.ToArray()), name, fileName);
7776
}
7877

79-
private void Add(HttpContent content, string name, string filename, string contentType)
80-
{
81-
if (filename != null)
82-
{
83-
Argument.AssertNotNullOrEmpty(filename, nameof(filename));
84-
AddFileNameHeader(content, name, filename);
85-
}
86-
if (contentType != null)
87-
{
88-
Argument.AssertNotNullOrEmpty(contentType, nameof(contentType));
89-
AddContentTypeHeader(content, contentType);
90-
}
91-
_multipartContent.Add(content, name);
92-
}
93-
9478
private void Add(HttpContent content, string name, string fileName)
9579
{
80+
Argument.AssertNotNull(content, nameof(content));
81+
Argument.AssertNotNull(name, nameof(name));
82+
9683
if (fileName is not null)
9784
{
98-
AddFileNameHeader(content, name, fileName);
85+
_multipartContent.Add(content, name, fileName);
9986
}
100-
101-
_multipartContent.Add(content, name);
102-
}
103-
104-
private static void AddFileNameHeader(HttpContent content, string name, string filename)
105-
{
106-
// Add the content header manually because the default implementation
107-
// adds a `filename*` parameter to the header, which RFC 7578 says not
108-
// to do. We are following up with the BCL team per correctness.
109-
ContentDispositionHeaderValue header = new("form-data")
87+
else
11088
{
111-
Name = name,
112-
FileName = filename
113-
};
114-
content.Headers.ContentDisposition = header;
115-
}
116-
117-
public static void AddContentTypeHeader(HttpContent content, string contentType)
118-
{
119-
MediaTypeHeaderValue header = new MediaTypeHeaderValue(contentType);
120-
content.Headers.ContentType = header;
89+
_multipartContent.Add(content, name);
90+
}
12191
}
12292

12393
#if NET6_0_OR_GREATER

tests/Files/FileTests.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,5 +83,17 @@ public void SerializeFileCollection()
8383
// TODO: Add this test.
8484
}
8585

86+
[Test]
87+
public async Task NonAsciiFilename()
88+
{
89+
FileClient client = GetTestClient();
90+
string filename = "你好.txt";
91+
BinaryData fileContent = BinaryData.FromString("世界您好!这是个测试。");
92+
OpenAIFileInfo uploadedFile = IsAsync
93+
? await client.UploadFileAsync(fileContent, filename, FileUploadPurpose.Assistants)
94+
: client.UploadFile(fileContent, filename, FileUploadPurpose.Assistants);
95+
Assert.That(uploadedFile?.Filename, Is.EqualTo(filename));
96+
}
97+
8698
private static FileClient GetTestClient() => GetTestClient<FileClient>(TestScenario.Files);
8799
}

0 commit comments

Comments
 (0)