Skip to content

Commit 40fbef3

Browse files
committed
implement uploading of files
1 parent 040e2ae commit 40fbef3

File tree

5 files changed

+125
-0
lines changed

5 files changed

+125
-0
lines changed

Src/Notion.Client/Models/File/FileObjectWithName.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ namespace Notion.Client
66
[JsonConverter(typeof(JsonSubtypes), "type")]
77
[JsonSubtypes.KnownSubTypeAttribute(typeof(UploadedFileWithName), "file")]
88
[JsonSubtypes.KnownSubTypeAttribute(typeof(ExternalFileWithName), "external")]
9+
[JsonSubtypes.KnownSubTypeAttribute(typeof(FileUploadWithName), "file_upload")]
910
public abstract class FileObjectWithName
1011
{
1112
[JsonProperty("type")]
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System;
2+
using Newtonsoft.Json;
3+
4+
namespace Notion.Client
5+
{
6+
public class FileUploadWithName : FileObjectWithName
7+
{
8+
public override string Type => "file_upload";
9+
10+
[JsonProperty("file_upload")]
11+
public Info FileUpload { get; set; }
12+
13+
public class Info
14+
{
15+
[JsonProperty("id")]
16+
public Guid Id { get; set; }
17+
}
18+
19+
}
20+
}

Src/Notion.Client/RestClient/IRestClient.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,7 @@ Task DeleteAsync(
3535
IDictionary<string, string> queryParams = null,
3636
IDictionary<string, string> headers = null,
3737
CancellationToken cancellationToken = default);
38+
39+
Task<RestClient.UploadResponse> Upload(string filePath, JsonSerializerSettings serializerSettings = null);
3840
}
3941
}

Src/Notion.Client/RestClient/RestClient.cs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.IO;
34
using System.Net.Http;
45
using System.Net.Http.Headers;
56
using System.Text;
@@ -91,6 +92,52 @@ public async Task DeleteAsync(
9192
await SendAsync(uri, HttpMethod.Delete, queryParams, headers, null, cancellationToken);
9293
}
9394

95+
public async Task<UploadResponse> Upload(string filePath, JsonSerializerSettings serializerSettings = null)
96+
{
97+
var response = await this.PostAsync<UploadResponse>("https://api.notion.com/v1/file_uploads",
98+
new UploadRequest {Mode = "single_part"});
99+
100+
using (var formData = new MultipartFormDataContent())
101+
{
102+
var fileStream = File.OpenRead(filePath);
103+
var fileContent = new StreamContent(fileStream);
104+
formData.Add(fileContent, "file", Path.GetFileName(filePath));
105+
106+
var uploadResponse = await this.SendAsync(response.UploadUrl, HttpMethod.Post, attachContent: message =>
107+
{
108+
message.Content = formData;
109+
});
110+
return await uploadResponse.ParseStreamAsync<UploadResponse>(serializerSettings);
111+
}
112+
}
113+
114+
public class UploadRequest
115+
{
116+
public string Mode { get; set; }
117+
}
118+
119+
public class UploadResponse
120+
{
121+
public Guid Id { get; set; }
122+
public string Object { get; set; }
123+
[JsonProperty("created_time")]
124+
public DateTime CreatedTime { get; set; }
125+
[JsonProperty("last_edited_time")]
126+
public DateTime LastEditedTime { get; set; }
127+
[JsonProperty("expiry_time")]
128+
public DateTime ExpiryTime { get; set; }
129+
[JsonProperty("upload_url")]
130+
public string UploadUrl { get; set; }
131+
public bool Archived { get; set; }
132+
public string Status { get; set; }
133+
public string Filename { get; set; }
134+
[JsonProperty("content_type")]
135+
public string ContentType { get; set; }
136+
[JsonProperty("request_id")]
137+
public Guid RequestId { get; set; }
138+
}
139+
140+
94141
private static ClientOptions MergeOptions(ClientOptions options)
95142
{
96143
return new ClientOptions

Test/Notion.IntegrationTests/PageClientTests.cs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ public async Task InitializeAsync()
5454
}
5555
},
5656
{ "Number", new NumberPropertySchema { Number = new Number { Format = "number" } } }
57+
{"Profile picture", new FilePropertySchema() { Files = new Dictionary<string, object>()}}
5758
},
5859
Parent = new ParentPageInput { PageId = _page.Id }
5960
};
@@ -179,6 +180,60 @@ public async Task Test_RetrievePagePropertyItemAsync()
179180
titleProperty.Title.PlainText.Should().Be("Test Page Title");
180181
});
181182
}
183+
184+
[Fact]
185+
public async Task Test_CanUploadAndSetProfilePicture()
186+
{
187+
// Arrange
188+
var upload = await Client.RestClient.Upload("/Users/kkuepper/Pictures/Scan.jpeg");
189+
190+
// Act
191+
var pagesCreateParameters = PagesCreateParametersBuilder
192+
.Create(new DatabaseParentInput {DatabaseId = _database.Id})
193+
.AddProperty("Name",
194+
new TitlePropertyValue
195+
{
196+
Title = new List<RichTextBase>
197+
{
198+
new RichTextText {Text = new Text {Content = "Test Page Title"}}
199+
}
200+
})
201+
.AddProperty("Number", new NumberPropertyValue() {Number = 123})
202+
.AddProperty("Profile picture",
203+
new FilesPropertyValue
204+
{
205+
Files = new List<FileObjectWithName>
206+
{
207+
new FileUploadWithName {FileUpload = new FileUploadWithName.Info {Id = upload.Id}}
208+
}
209+
}
210+
)
211+
.Build();
212+
213+
var page = await Client.Pages.CreateAsync(pagesCreateParameters);
214+
215+
var property = await Client.Pages.RetrievePagePropertyItemAsync(new RetrievePropertyItemParameters
216+
{
217+
PageId = page.Id,
218+
PropertyId = "Profile picture"
219+
});
220+
221+
// Assert
222+
property.Should().NotBeNull();
223+
property.Should().BeOfType<FilesPropertyItem>();
224+
225+
var listProperty = (FilesPropertyItem)property;
226+
227+
listProperty.Type.Should().NotBeNull();
228+
229+
listProperty.Files.Should().SatisfyRespectively(p =>
230+
{
231+
p.Should().BeOfType<UploadedFileWithName>();
232+
var fileWithName = (UploadedFileWithName)p;
233+
234+
fileWithName.Name.Should().Be("Scan.jpeg");
235+
});
236+
}
182237

183238
[Fact]
184239
public async Task Test_UpdatePageProperty_with_date_as_null()

0 commit comments

Comments
 (0)