Skip to content

Commit 76b1513

Browse files
feat: Support getting file download URL and file thumbnail URL (box/box-codegen#642) (#374)
1 parent 3361ad1 commit 76b1513

19 files changed

+474
-15
lines changed

.codegen.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{ "engineHash": "b2c3124", "specHash": "0a89b2b", "version": "1.5.0" }
1+
{ "engineHash": "553616e", "specHash": "cf0a265", "version": "1.5.0" }

Box.Sdk.Gen.Tests.Integration/Test/Downloads/DownloadsManagerTests.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,14 @@ public async System.Threading.Tasks.Task TestDownloadFile() {
2424
await client.Files.DeleteFileByIdAsync(fileId: uploadedFile.Id);
2525
}
2626

27+
[TestMethod]
28+
public async System.Threading.Tasks.Task TestGetDownloadUrl() {
29+
FileFull uploadedFile = await new CommonsManager().UploadNewFileAsync();
30+
string downloadUrl = await client.Downloads.GetDownloadFileUrlAsync(fileId: uploadedFile.Id);
31+
Assert.IsTrue(downloadUrl != null);
32+
Assert.IsTrue(downloadUrl.Contains("https://"));
33+
await client.Files.DeleteFileByIdAsync(fileId: uploadedFile.Id);
34+
}
35+
2736
}
2837
}

Box.Sdk.Gen.Tests.Integration/Test/Files/FilesManagerTests.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,17 @@ public async System.Threading.Tasks.Task<FileFull> UploadFileAsync(string fileNa
2020
return NullableUtils.Unwrap(uploadedFiles.Entries)[0];
2121
}
2222

23+
[TestMethod]
24+
public async System.Threading.Tasks.Task TestGetFileThumbnailUrl() {
25+
string thumbnailFileName = Utils.GetUUID();
26+
System.IO.Stream thumbnailContentStream = Utils.GenerateByteStream(size: 1024 * 1024);
27+
FileFull thumbnailFile = await UploadFileAsync(fileName: thumbnailFileName, fileStream: thumbnailContentStream);
28+
string downloadUrl = await client.Files.GetFileThumbnailUrlAsync(fileId: thumbnailFile.Id, extension: GetFileThumbnailUrlExtension.Png);
29+
Assert.IsTrue(downloadUrl != null);
30+
Assert.IsTrue(downloadUrl.Contains("https://"));
31+
await client.Files.DeleteFileByIdAsync(fileId: thumbnailFile.Id);
32+
}
33+
2334
[TestMethod]
2435
public async System.Threading.Tasks.Task TestGetFileThumbnail() {
2536
string thumbnailFileName = Utils.GetUUID();

Box.Sdk.Gen/Box/JwtAuth/JwtConfig.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public class JwtConfig {
4242
/// </summary>
4343
public string? UserId { get; init; }
4444

45-
internal JwtAlgorithm? Algorithm { get; }
45+
internal JwtAlgorithm? Algorithm { get; init; } = JwtAlgorithm.Rs256;
4646

4747
public ITokenStorage TokenStorage { get; }
4848

Box.Sdk.Gen/Client/BoxClient.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ public BoxClient(IAuthentication auth, NetworkSession? networkSession = default)
232232
public async System.Threading.Tasks.Task<FetchResponse> MakeRequestAsync(FetchOptions fetchOptions) {
233233
IAuthentication auth = fetchOptions.Auth == null ? this.Auth : NullableUtils.Unwrap(fetchOptions.Auth);
234234
NetworkSession networkSession = fetchOptions.NetworkSession == null ? this.NetworkSession : NullableUtils.Unwrap(fetchOptions.NetworkSession);
235-
FetchOptions enrichedFetchOptions = new FetchOptions(url: fetchOptions.Url, method: fetchOptions.Method, contentType: fetchOptions.ContentType, responseFormat: fetchOptions.ResponseFormat) { Auth = auth, NetworkSession = networkSession, Parameters = fetchOptions.Parameters, Headers = fetchOptions.Headers, Data = fetchOptions.Data, FileStream = fetchOptions.FileStream, MultipartData = fetchOptions.MultipartData };
235+
FetchOptions enrichedFetchOptions = new FetchOptions(url: fetchOptions.Url, method: fetchOptions.Method, contentType: fetchOptions.ContentType, responseFormat: fetchOptions.ResponseFormat) { Auth = auth, NetworkSession = networkSession, Parameters = fetchOptions.Parameters, Headers = fetchOptions.Headers, Data = fetchOptions.Data, FileStream = fetchOptions.FileStream, MultipartData = fetchOptions.MultipartData, FollowRedirects = fetchOptions.FollowRedirects };
236236
return await networkSession.NetworkClient.FetchAsync(options: enrichedFetchOptions).ConfigureAwait(false);
237237
}
238238

Box.Sdk.Gen/Managers/Downloads/DownloadsManager.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,43 @@ public class DownloadsManager : IDownloadsManager {
1313
public DownloadsManager(NetworkSession? networkSession = default) {
1414
NetworkSession = networkSession ?? new NetworkSession();
1515
}
16+
/// <summary>
17+
/// Returns the contents of a file in binary format.
18+
/// </summary>
19+
/// <param name="fileId">
20+
/// The unique identifier that represents a file.
21+
///
22+
/// The ID for any file can be determined
23+
/// by visiting a file in the web application
24+
/// and copying the ID from the URL. For example,
25+
/// for the URL `https://*.app.box.com/files/123`
26+
/// the `file_id` is `123`.
27+
/// Example: "12345"
28+
/// </param>
29+
/// <param name="queryParams">
30+
/// Query parameters of downloadFile method
31+
/// </param>
32+
/// <param name="headers">
33+
/// Headers of downloadFile method
34+
/// </param>
35+
/// <param name="cancellationToken">
36+
/// Token used for request cancellation.
37+
/// </param>
38+
public async System.Threading.Tasks.Task<string> GetDownloadFileUrlAsync(string fileId, GetDownloadFileUrlQueryParams? queryParams = default, GetDownloadFileUrlHeaders? headers = default, System.Threading.CancellationToken? cancellationToken = null) {
39+
queryParams = queryParams ?? new GetDownloadFileUrlQueryParams();
40+
headers = headers ?? new GetDownloadFileUrlHeaders();
41+
Dictionary<string, string> queryParamsMap = Utils.PrepareParams(map: new Dictionary<string, string?>() { { "version", StringUtils.ToStringRepresentation(queryParams.Version) }, { "access_token", StringUtils.ToStringRepresentation(queryParams.AccessTokenField) } });
42+
Dictionary<string, string> headersMap = Utils.PrepareParams(map: DictionaryUtils.MergeDictionaries(new Dictionary<string, string?>() { { "range", StringUtils.ToStringRepresentation(headers.Range) }, { "boxapi", StringUtils.ToStringRepresentation(headers.Boxapi) } }, headers.ExtraHeaders));
43+
FetchResponse response = await this.NetworkSession.NetworkClient.FetchAsync(options: new FetchOptions(url: string.Concat(this.NetworkSession.BaseUrls.BaseUrl, "/2.0/files/", StringUtils.ToStringRepresentation(fileId), "/content"), method: "GET", responseFormat: Box.Sdk.Gen.ResponseFormat.NoContent) { Parameters = queryParamsMap, Headers = headersMap, Auth = this.Auth, NetworkSession = this.NetworkSession, CancellationToken = cancellationToken, FollowRedirects = false }).ConfigureAwait(false);
44+
if (response.Headers.ContainsKey("location")) {
45+
return response.Headers["location"];
46+
}
47+
if (response.Headers.ContainsKey("Location")) {
48+
return response.Headers["Location"];
49+
}
50+
throw new BoxSdkException(message: "No location header in response");
51+
}
52+
1653
/// <summary>
1754
/// Returns the contents of a file in binary format.
1855
/// </summary>
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using Box.Sdk.Gen;
2+
using System.Collections.Generic;
3+
using System.Collections.ObjectModel;
4+
using Box.Sdk.Gen.Internal;
5+
using Box.Sdk.Gen.Schemas;
6+
7+
namespace Box.Sdk.Gen.Managers {
8+
public class GetDownloadFileUrlHeaders {
9+
/// <summary>
10+
/// The byte range of the content to download.
11+
///
12+
/// The format `bytes={start_byte}-{end_byte}` can be used to specify
13+
/// what section of the file to download.
14+
/// </summary>
15+
public string? Range { get; init; }
16+
17+
/// <summary>
18+
/// The URL, and optional password, for the shared link of this item.
19+
///
20+
/// This header can be used to access items that have not been
21+
/// explicitly shared with a user.
22+
///
23+
/// Use the format `shared_link=[link]` or if a password is required then
24+
/// use `shared_link=[link]&shared_link_password=[password]`.
25+
///
26+
/// This header can be used on the file or folder shared, as well as on any files
27+
/// or folders nested within the item.
28+
/// </summary>
29+
public string? Boxapi { get; init; }
30+
31+
/// <summary>
32+
/// Extra headers that will be included in the HTTP request.
33+
/// </summary>
34+
public Dictionary<string, string?> ExtraHeaders { get; }
35+
36+
public GetDownloadFileUrlHeaders(Dictionary<string, string?>? extraHeaders = default) {
37+
ExtraHeaders = extraHeaders ?? new Dictionary<string, string?>() { };
38+
}
39+
}
40+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using Box.Sdk.Gen;
2+
using System.Collections.Generic;
3+
using System.Collections.ObjectModel;
4+
using Box.Sdk.Gen.Internal;
5+
using Box.Sdk.Gen.Schemas;
6+
7+
namespace Box.Sdk.Gen.Managers {
8+
public class GetDownloadFileUrlQueryParams {
9+
/// <summary>
10+
/// The file version to download
11+
/// </summary>
12+
public string? Version { get; init; }
13+
14+
/// <summary>
15+
/// An optional access token that can be used to pre-authenticate this request, which means that a download link can be shared with a browser or a third party service without them needing to know how to handle the authentication.
16+
/// When using this parameter, please make sure that the access token is sufficiently scoped down to only allow read access to that file and no other files or folders.
17+
/// </summary>
18+
public string? AccessTokenField { get; init; }
19+
20+
public GetDownloadFileUrlQueryParams() {
21+
22+
}
23+
}
24+
}

Box.Sdk.Gen/Managers/Downloads/IDownloadsManager.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,30 @@ public interface IDownloadsManager {
2828
/// <param name="cancellationToken">
2929
/// Token used for request cancellation.
3030
/// </param>
31+
public System.Threading.Tasks.Task<string> GetDownloadFileUrlAsync(string fileId, GetDownloadFileUrlQueryParams? queryParams = default, GetDownloadFileUrlHeaders? headers = default, System.Threading.CancellationToken? cancellationToken = null) => throw new System.NotImplementedException("This method needs to be implemented by the derived class before calling it.");
32+
33+
/// <summary>
34+
/// Returns the contents of a file in binary format.
35+
/// </summary>
36+
/// <param name="fileId">
37+
/// The unique identifier that represents a file.
38+
///
39+
/// The ID for any file can be determined
40+
/// by visiting a file in the web application
41+
/// and copying the ID from the URL. For example,
42+
/// for the URL `https://*.app.box.com/files/123`
43+
/// the `file_id` is `123`.
44+
/// Example: "12345"
45+
/// </param>
46+
/// <param name="queryParams">
47+
/// Query parameters of downloadFile method
48+
/// </param>
49+
/// <param name="headers">
50+
/// Headers of downloadFile method
51+
/// </param>
52+
/// <param name="cancellationToken">
53+
/// Token used for request cancellation.
54+
/// </param>
3155
public System.Threading.Tasks.Task<System.IO.Stream?> DownloadFileAsync(string fileId, DownloadFileQueryParams? queryParams = default, DownloadFileHeaders? headers = default, System.Threading.CancellationToken? cancellationToken = null) => throw new System.NotImplementedException("This method needs to be implemented by the derived class before calling it.");
3256

3357
}

Box.Sdk.Gen/Managers/Files/FilesManager.cs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,56 @@ public async System.Threading.Tasks.Task<FileFull> CopyFileAsync(string fileId,
145145
return SimpleJsonSerializer.Deserialize<FileFull>(NullableUtils.Unwrap(response.Data));
146146
}
147147

148+
/// <summary>
149+
/// Retrieves a thumbnail, or smaller image representation, of a file.
150+
///
151+
/// Sizes of `32x32`,`64x64`, `128x128`, and `256x256` can be returned in
152+
/// the `.png` format and sizes of `32x32`, `160x160`, and `320x320`
153+
/// can be returned in the `.jpg` format.
154+
///
155+
/// Thumbnails can be generated for the image and video file formats listed
156+
/// [found on our community site][1].
157+
///
158+
/// [1]: https://community.box.com/t5/Migrating-and-Previewing-Content/File-Types-and-Fonts-Supported-in-Box-Content-Preview/ta-p/327
159+
/// </summary>
160+
/// <param name="fileId">
161+
/// The unique identifier that represents a file.
162+
///
163+
/// The ID for any file can be determined
164+
/// by visiting a file in the web application
165+
/// and copying the ID from the URL. For example,
166+
/// for the URL `https://*.app.box.com/files/123`
167+
/// the `file_id` is `123`.
168+
/// Example: "12345"
169+
/// </param>
170+
/// <param name="extension">
171+
/// The file format for the thumbnail
172+
/// Example: "png"
173+
/// </param>
174+
/// <param name="queryParams">
175+
/// Query parameters of getFileThumbnailById method
176+
/// </param>
177+
/// <param name="headers">
178+
/// Headers of getFileThumbnailById method
179+
/// </param>
180+
/// <param name="cancellationToken">
181+
/// Token used for request cancellation.
182+
/// </param>
183+
public async System.Threading.Tasks.Task<string> GetFileThumbnailUrlAsync(string fileId, GetFileThumbnailUrlExtension extension, GetFileThumbnailUrlQueryParams? queryParams = default, GetFileThumbnailUrlHeaders? headers = default, System.Threading.CancellationToken? cancellationToken = null) {
184+
queryParams = queryParams ?? new GetFileThumbnailUrlQueryParams();
185+
headers = headers ?? new GetFileThumbnailUrlHeaders();
186+
Dictionary<string, string> queryParamsMap = Utils.PrepareParams(map: new Dictionary<string, string?>() { { "min_height", StringUtils.ToStringRepresentation(queryParams.MinHeight) }, { "min_width", StringUtils.ToStringRepresentation(queryParams.MinWidth) }, { "max_height", StringUtils.ToStringRepresentation(queryParams.MaxHeight) }, { "max_width", StringUtils.ToStringRepresentation(queryParams.MaxWidth) } });
187+
Dictionary<string, string> headersMap = Utils.PrepareParams(map: DictionaryUtils.MergeDictionaries(new Dictionary<string, string?>() { }, headers.ExtraHeaders));
188+
FetchResponse response = await this.NetworkSession.NetworkClient.FetchAsync(options: new FetchOptions(url: string.Concat(this.NetworkSession.BaseUrls.BaseUrl, "/2.0/files/", StringUtils.ToStringRepresentation(fileId), "/thumbnail.", StringUtils.ToStringRepresentation(extension)), method: "GET", responseFormat: Box.Sdk.Gen.ResponseFormat.NoContent) { Parameters = queryParamsMap, Headers = headersMap, Auth = this.Auth, NetworkSession = this.NetworkSession, CancellationToken = cancellationToken, FollowRedirects = false }).ConfigureAwait(false);
189+
if (response.Headers.ContainsKey("location")) {
190+
return response.Headers["location"];
191+
}
192+
if (response.Headers.ContainsKey("Location")) {
193+
return response.Headers["Location"];
194+
}
195+
throw new BoxSdkException(message: "No location header in response");
196+
}
197+
148198
/// <summary>
149199
/// Retrieves a thumbnail, or smaller image representation, of a file.
150200
///

0 commit comments

Comments
 (0)