Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 8f36074

Browse files
committedJan 29, 2025··
Refactor form data and MIME handling
1 parent 108aab0 commit 8f36074

File tree

6 files changed

+58
-41
lines changed

6 files changed

+58
-41
lines changed
 

‎src/Todoist.Net/IAdvancedTodoistClient.cs

+4-2
Original file line numberDiff line numberDiff line change
@@ -88,15 +88,17 @@ Task<T> PostFormAsync<T>(
8888
/// </summary>
8989
/// <typeparam name="T">The result type.</typeparam>
9090
/// <param name="resource">The resource.</param>
91-
/// <param name="data">The form data.</param>
91+
/// <param name="parameters">The parameters.</param>
92+
/// <param name="files">The files.</param>
9293
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
9394
/// <returns>
9495
/// The result.
9596
/// </returns>
9697
/// <exception cref="HttpRequestException">API exception.</exception>
9798
Task<T> PostFormAsync<T>(
9899
string resource,
99-
MultipartFormDataContent data,
100+
ICollection<KeyValuePair<string, string>> parameters,
101+
IEnumerable<FormFile> files,
100102
CancellationToken cancellationToken = default);
101103

102104
/// <summary>

‎src/Todoist.Net/Models/FormFile.cs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
namespace Todoist.Net.Models
2+
{
3+
internal class FormFile
4+
{
5+
public FormFile(byte[] content, string filename, string mimeType = null)
6+
{
7+
Content = content;
8+
Filename = filename;
9+
MimeType = mimeType;
10+
}
11+
12+
public byte[] Content;
13+
public string Filename;
14+
public string MimeType;
15+
}
16+
}

‎src/Todoist.Net/Services/IUploadService.cs

-12
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,5 @@ public interface IUploadService
4040
/// <returns>The uploaded file.</returns>
4141
/// <exception cref="HttpRequestException">API exception.</exception>
4242
Task<FileAttachment> UploadAsync(string fileName, byte[] fileContent, CancellationToken cancellationToken = default);
43-
44-
45-
/// <summary>
46-
/// Uploads a file asynchronous.
47-
/// </summary>
48-
/// <param name="fileName">Name of the file.</param>
49-
/// <param name="fileContent">Content of the file.</param>
50-
/// <param name="mimeType">MIME type of the file.</param>
51-
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
52-
/// <returns>The uploaded file.</returns>
53-
/// <exception cref="HttpRequestException">API exception.</exception>
54-
Task<FileAttachment> UploadAsync(string fileName, string mimeType, byte[] fileContent, CancellationToken cancellationToken = default);
5543
}
5644
}

‎src/Todoist.Net/Services/UploadService.cs

+19-26
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@
44
using System.Threading;
55
using System.Threading.Tasks;
66

7+
#if NETSTANDARD2_0
8+
using Microsoft.AspNetCore.StaticFiles;
9+
#else
10+
using System.Web;
11+
#endif
12+
713
using Todoist.Net.Models;
814

915
namespace Todoist.Net.Services
@@ -16,6 +22,10 @@ internal class UploadService : IUploadService
1622
{
1723
private readonly IAdvancedTodoistClient _todoistClient;
1824

25+
#if NETSTANDARD2_0
26+
private static readonly FileExtensionContentTypeProvider MimeProvider = new FileExtensionContentTypeProvider();
27+
#endif
28+
1929
internal UploadService(IAdvancedTodoistClient todoistClient)
2030
{
2131
_todoistClient = todoistClient;
@@ -45,34 +55,17 @@ public Task<FileAttachment> UploadAsync(
4555
string fileName, byte[] fileContent, CancellationToken cancellationToken = default
4656
)
4757
{
48-
var data = new MultipartFormDataContent
49-
{
50-
{
51-
new ByteArrayContent(fileContent), "file", fileName
52-
}
53-
};
54-
55-
return _todoistClient.PostFormAsync<FileAttachment>("uploads/add", data, cancellationToken);
56-
}
58+
#if NETSTANDARD2_0
59+
MimeProvider.TryGetContentType(fileName, out var mimeType);
60+
#else
61+
var mimeType = MimeMapping.GetMimeMapping(fileName);
62+
#endif
5763

58-
/// <inheritdoc/>
59-
public Task<FileAttachment> UploadAsync(
60-
string fileName, string mimeType, byte[] fileContent, CancellationToken cancellationToken = default
61-
)
62-
{
63-
var mime = mimeType != null ? MediaTypeHeaderValue.Parse(mimeType) : null;
64-
var data = new MultipartFormDataContent
65-
{
66-
{
67-
new ByteArrayContent(fileContent)
68-
{
69-
Headers = { ContentType = mime }
70-
},
71-
"file", fileName
72-
}
73-
};
64+
var parameters = new Dictionary<string, string>();
65+
var file = new FormFile(fileContent, fileName, mimeType);
66+
var files = new[] { file };
7467

75-
return _todoistClient.PostFormAsync<FileAttachment>("uploads/add", data, cancellationToken);
68+
return _todoistClient.PostFormAsync<FileAttachment>("uploads/add", parameters, files, cancellationToken);
7669
}
7770
}
7871
}

‎src/Todoist.Net/Todoist.Net.csproj

+2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232
<ItemGroup Condition=" '$(TargetFramework)' == 'net462' ">
3333
<Reference Include="System.Net.Http" />
34+
<Reference Include="System.Web" />
3435
</ItemGroup>
3536

3637
<ItemGroup>
@@ -46,6 +47,7 @@
4647

4748
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
4849
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.1" />
50+
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.3.0" />
4951
</ItemGroup>
5052

5153
</Project>

‎src/Todoist.Net/TodoistClient.cs

+17-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Linq;
44
using System.Net;
55
using System.Net.Http;
6+
using System.Net.Http.Headers;
67
using System.Text.Json;
78
using System.Text.Json.Serialization;
89
using System.Text.Json.Serialization.Metadata;
@@ -301,9 +302,24 @@ Task<T> IAdvancedTodoistClient.PostFormAsync<T>(
301302
/// <inheritdoc/>
302303
Task<T> IAdvancedTodoistClient.PostFormAsync<T>(
303304
string resource,
304-
MultipartFormDataContent data,
305+
ICollection<KeyValuePair<string, string>> parameters,
306+
IEnumerable<FormFile> files,
305307
CancellationToken cancellationToken)
306308
{
309+
var data = new MultipartFormDataContent();
310+
311+
foreach (var file in files)
312+
{
313+
var mime = file.MimeType != null ? MediaTypeHeaderValue.Parse(file.MimeType) : null;
314+
var content = new ByteArrayContent(file.Content) { Headers = { ContentType = mime } };
315+
data.Add(content, "file", file.Filename);
316+
}
317+
318+
foreach (var keyValuePair in parameters)
319+
{
320+
data.Add(new StringContent(keyValuePair.Value), $"\"{keyValuePair.Key}\"");
321+
}
322+
307323
return ProcessFormAsync<T>(resource, data, cancellationToken);
308324
}
309325

0 commit comments

Comments
 (0)
Please sign in to comment.