diff --git a/benchmarks/RestSharp.Benchmarks/RestSharp.Benchmarks.csproj b/benchmarks/RestSharp.Benchmarks/RestSharp.Benchmarks.csproj
index 8644bb21b..e1da87b9a 100644
--- a/benchmarks/RestSharp.Benchmarks/RestSharp.Benchmarks.csproj
+++ b/benchmarks/RestSharp.Benchmarks/RestSharp.Benchmarks.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/docs/error-handling.md b/docs/error-handling.md
index 01b96b6da..60508ee3f 100644
--- a/docs/error-handling.md
+++ b/docs/error-handling.md
@@ -63,4 +63,4 @@ Below you can find how different extensions deal with errors. Note that function
| `HeadAsync` | Yes |
| `HeadAsync` | Yes |
-In addition, all the functions for JSON requests, like `GetJsonAsync` and `PostJsonAsyn` throw an exception if the HTTP call fails.
+In addition, all the functions for JSON requests, like `GetJsonAsync` and `PostJsonAsync` throw an exception if the HTTP call fails.
diff --git a/docs/usage.md b/docs/usage.md
index 8e41cc314..150df78f8 100644
--- a/docs/usage.md
+++ b/docs/usage.md
@@ -561,6 +561,22 @@ AddFile(parameterName, getFile, fileName, contentType);
Remember that `AddFile` will set all the necessary headers, so please don't try to set content headers manually.
+You can also provide file upload options to the `AddFile` call. The options are:
+- `DisableFilenameEncoding` (default `false`): if set to `true`, RestSharp will not encode the file name in the `Content-Disposition` header
+- `DisableFilenameStar` (default `true`): if set to `true`, RestSharp will not add the `filename*` parameter to the `Content-Disposition` header
+
+Example of using the options:
+
+```csharp
+var options = new FileParameterOptions {
+ DisableFilenameEncoding = true,
+ DisableFilenameStar = false
+};
+request.AddFile("file", filePath, options: options);
+```
+
+The options specified in the snippet above usually help when you upload files with non-ASCII characters in their names.
+
### Downloading binary data
There are two functions that allow you to download binary data from the remote API.
diff --git a/props/Common.props b/props/Common.props
index e876e299a..26bf7321a 100644
--- a/props/Common.props
+++ b/props/Common.props
@@ -7,4 +7,7 @@
enable
enable
+
+
+
\ No newline at end of file
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 13dd1b1c0..69705872a 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -21,7 +21,7 @@
-
+
diff --git a/src/RestSharp.Serializers.CsvHelper/CsvHelperSerializer.cs b/src/RestSharp.Serializers.CsvHelper/CsvHelperSerializer.cs
index 318139ef0..96c19536c 100644
--- a/src/RestSharp.Serializers.CsvHelper/CsvHelperSerializer.cs
+++ b/src/RestSharp.Serializers.CsvHelper/CsvHelperSerializer.cs
@@ -84,19 +84,7 @@ public class CsvHelperSerializer : IDeserializer, IRestSerializer, ISerializer {
using var csvWriter = new CsvWriter(stringWriter, _configuration);
if (obj is IEnumerable records) {
- // ReSharper disable once PossibleMultipleEnumeration
- var enumerator = records.GetEnumerator();
-
- if (enumerator.MoveNext() && enumerator.Current != null) {
- csvWriter.WriteHeader(enumerator.Current.GetType());
- csvWriter.NextRecord();
- // ReSharper disable once PossibleMultipleEnumeration
- csvWriter.WriteRecords(records);
- }
-
- if (enumerator is IDisposable disposable) {
- disposable.Dispose();
- }
+ csvWriter.WriteRecords(records);
}
else {
csvWriter.WriteHeader(obj.GetType());
diff --git a/src/RestSharp.Serializers.CsvHelper/RestSharp.Serializers.CsvHelper.csproj b/src/RestSharp.Serializers.CsvHelper/RestSharp.Serializers.CsvHelper.csproj
index 2168d422a..5fff5b301 100644
--- a/src/RestSharp.Serializers.CsvHelper/RestSharp.Serializers.CsvHelper.csproj
+++ b/src/RestSharp.Serializers.CsvHelper/RestSharp.Serializers.CsvHelper.csproj
@@ -1,6 +1,6 @@
-
+
diff --git a/src/RestSharp/Parameters/FileParameter.cs b/src/RestSharp/Parameters/FileParameter.cs
index 75b314aa0..5b58bf44d 100644
--- a/src/RestSharp/Parameters/FileParameter.cs
+++ b/src/RestSharp/Parameters/FileParameter.cs
@@ -113,6 +113,11 @@ public static FileParameter FromFile(
[PublicAPI]
public class FileParameterOptions {
- public bool DisableFileNameStar { get; set; } = true;
+ [Obsolete("Use DisableFilenameStar instead")]
+ public bool DisableFileNameStar {
+ get => DisableFilenameStar;
+ set => DisableFilenameStar = value;
+ }
+ public bool DisableFilenameStar { get; set; } = true;
public bool DisableFilenameEncoding { get; set; }
}
diff --git a/test/Directory.Build.props b/test/Directory.Build.props
index 4597143db..ec109e2e1 100644
--- a/test/Directory.Build.props
+++ b/test/Directory.Build.props
@@ -9,14 +9,14 @@
-
-
+
+
-
+
-
+
diff --git a/test/RestSharp.Tests.Integrated/RestSharp.Tests.Integrated.csproj b/test/RestSharp.Tests.Integrated/RestSharp.Tests.Integrated.csproj
index 92691e7f4..cd511eb9b 100644
--- a/test/RestSharp.Tests.Integrated/RestSharp.Tests.Integrated.csproj
+++ b/test/RestSharp.Tests.Integrated/RestSharp.Tests.Integrated.csproj
@@ -16,10 +16,8 @@
-
-
-
+
diff --git a/test/RestSharp.Tests.Integrated/Server/Handlers/FileHandlers.cs b/test/RestSharp.Tests.Integrated/Server/Handlers/FileHandlers.cs
index d7cc03811..56740fc7f 100644
--- a/test/RestSharp.Tests.Integrated/Server/Handlers/FileHandlers.cs
+++ b/test/RestSharp.Tests.Integrated/Server/Handlers/FileHandlers.cs
@@ -10,17 +10,27 @@ public class UploadController : ControllerBase {
[HttpPost]
[Route("upload")]
[SuppressMessage("Performance", "CA1822:Mark members as static")]
- public async Task Upload([FromForm] FormFile formFile) {
+ public async Task Upload([FromForm] FormFile formFile, [FromQuery] bool checkFile = true) {
+ var file = formFile.File;
+
+ if (!checkFile) {
+ return Ok(new UploadResponse(file.FileName, file.Length, true));
+ }
+
var assetPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Assets");
- var file = formFile.File;
await using var stream = file.OpenReadStream();
var received = await stream.ReadAsBytes(default);
- var expected = await System.IO.File.ReadAllBytesAsync(Path.Combine(assetPath, file.FileName));
- var response = new UploadResponse(file.FileName, file.Length, received.SequenceEqual(expected));
- return response;
+ try {
+ var expected = await System.IO.File.ReadAllBytesAsync(Path.Combine(assetPath, file.FileName));
+ var response = new UploadResponse(file.FileName, file.Length, received.SequenceEqual(expected));
+ return Ok(response);
+ }
+ catch (Exception e) {
+ return BadRequest(new { Message = e.Message, Filename = file.FileName });
+ }
}
}
diff --git a/test/RestSharp.Tests.Integrated/UploadFileTests.cs b/test/RestSharp.Tests.Integrated/UploadFileTests.cs
index 843e9048e..fd9f2c498 100644
--- a/test/RestSharp.Tests.Integrated/UploadFileTests.cs
+++ b/test/RestSharp.Tests.Integrated/UploadFileTests.cs
@@ -7,58 +7,63 @@ namespace RestSharp.Tests.Integrated;
public class UploadFileTests {
readonly ITestOutputHelper _output;
readonly RestClient _client;
- readonly string _path = AppDomain.CurrentDomain.BaseDirectory;
+ readonly string _basePath = AppDomain.CurrentDomain.BaseDirectory;
+ readonly string _path;
+ readonly UploadResponse _expected;
+
+ const string Filename = "Koala.jpg";
public UploadFileTests(TestServerFixture fixture, ITestOutputHelper output) {
_output = output;
- _client = new RestClient(new RestClientOptions(fixture.Server.Url) { ThrowOnAnyError = true });
+ // _client = new RestClient(new RestClientOptions(fixture.Server.Url) { ThrowOnAnyError = true });
+ _client = new RestClient(new RestClientOptions(fixture.Server.Url) { ThrowOnAnyError = false });
+ _path = Path.Combine(_basePath, "Assets", Filename);
+ _expected = new UploadResponse(Filename, new FileInfo(_path).Length, true);
}
[Fact]
public async Task Should_upload_from_file() {
- const string filename = "Koala.jpg";
-
- var path = Path.Combine(_path, "Assets", filename);
-
- var request = new RestRequest("upload").AddFile("file", path);
+ var request = new RestRequest("upload").AddFile("file", _path);
var response = await _client.ExecutePostAsync(request);
response.StatusCode.Should().Be(HttpStatusCode.OK);
- var expected = new UploadResponse(filename, new FileInfo(path).Length, true);
-
_output.WriteLine(response.Content);
- response.Data.Should().BeEquivalentTo(expected);
+ response.Data.Should().BeEquivalentTo(_expected);
}
[Fact]
public async Task Should_upload_from_bytes() {
- const string filename = "Koala.jpg";
+ var bytes = await File.ReadAllBytesAsync(_path);
- var path = Path.Combine(_path, "Assets", filename);
- var bytes = await File.ReadAllBytesAsync(path);
-
- var request = new RestRequest("upload").AddFile("file", bytes, filename);
+ var request = new RestRequest("upload").AddFile("file", bytes, Filename);
var response = await _client.ExecutePostAsync(request);
- var expected = new UploadResponse(filename, new FileInfo(path).Length, true);
-
_output.WriteLine(response.Content);
- response.Data.Should().BeEquivalentTo(expected);
+ response.Data.Should().BeEquivalentTo(_expected);
}
[Fact]
public async Task Should_upload_from_stream() {
- const string filename = "Koala.jpg";
+ var request = new RestRequest("upload").AddFile("file", () => File.OpenRead(_path), Filename);
+ var response = await _client.ExecutePostAsync(request);
- var path = Path.Combine(_path, "Assets", filename);
+ _output.WriteLine(response.Content);
+ response.Data.Should().BeEquivalentTo(_expected);
+ }
- var request = new RestRequest("upload").AddFile("file", () => File.OpenRead(path), filename);
- var response = await _client.ExecutePostAsync(request);
+ [Fact]
+ public async Task Should_upload_from_stream_non_ascii() {
+ const string nonAsciiFilename = "Präsentation_Export.zip";
+
+ var options = new FileParameterOptions { DisableFilenameEncoding = true, DisableFilenameStar = false};
- var expected = new UploadResponse(filename, new FileInfo(path).Length, true);
+ var request = new RestRequest("upload")
+ .AddFile("file", () => File.OpenRead(_path), nonAsciiFilename, options: options)
+ .AddQueryParameter("checkFile", "false");
+ var response = await _client.ExecutePostAsync(request);
_output.WriteLine(response.Content);
- response.Data.Should().BeEquivalentTo(expected);
+ response.Data.Should().BeEquivalentTo(new UploadResponse(nonAsciiFilename, new FileInfo(_path).Length, true));
}
}
diff --git a/test/RestSharp.Tests.Serializers.Csv/CsvHelperTests.cs b/test/RestSharp.Tests.Serializers.Csv/CsvHelperTests.cs
index 5901d14d1..e4aee68e8 100644
--- a/test/RestSharp.Tests.Serializers.Csv/CsvHelperTests.cs
+++ b/test/RestSharp.Tests.Serializers.Csv/CsvHelperTests.cs
@@ -137,11 +137,12 @@ public void SerializedObject_Should_Be() {
DateTimeValue = new DateTime(2024, 1, 20)
};
- serializer.Serialize(item)
- .Should()
- .Be(
- "StringValue,Int32Value,DecimalValue,DoubleValue,SingleValue,DateTimeValue,TimeSpanValue;hello,32,0,0,16.5,01/20/2024 00:00:00,00:10:00;"
- );
+ var actual = serializer.Serialize(item);
+
+ const string expected =
+ "StringValue,Int32Value,DecimalValue,DoubleValue,SingleValue,DateTimeValue,TimeSpanValue;hello,32,0,0,16.5,01/20/2024 00:00:00,00:10:00;";
+
+ actual.Should().Be(expected);
}
[Fact]
diff --git a/test/RestSharp.Tests/RestSharp.Tests.csproj b/test/RestSharp.Tests/RestSharp.Tests.csproj
index cdae3f398..eda460e5b 100644
--- a/test/RestSharp.Tests/RestSharp.Tests.csproj
+++ b/test/RestSharp.Tests/RestSharp.Tests.csproj
@@ -1,6 +1,6 @@
-
+