Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Support getting file download URL and file thumbnail URL (box/box-codegen#642) #374

Merged
merged 11 commits into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .codegen.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{ "engineHash": "b2c3124", "specHash": "0a89b2b", "version": "1.5.0" }
{ "engineHash": "553616e", "specHash": "cf0a265", "version": "1.5.0" }
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,14 @@ public async System.Threading.Tasks.Task TestDownloadFile() {
await client.Files.DeleteFileByIdAsync(fileId: uploadedFile.Id);
}

[TestMethod]
public async System.Threading.Tasks.Task TestGetDownloadUrl() {
FileFull uploadedFile = await new CommonsManager().UploadNewFileAsync();
string downloadUrl = await client.Downloads.GetDownloadFileUrlAsync(fileId: uploadedFile.Id);
Assert.IsTrue(downloadUrl != null);
Assert.IsTrue(downloadUrl.Contains("https://"));
await client.Files.DeleteFileByIdAsync(fileId: uploadedFile.Id);
}

}
}
11 changes: 11 additions & 0 deletions Box.Sdk.Gen.Tests.Integration/Test/Files/FilesManagerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,17 @@ public async System.Threading.Tasks.Task<FileFull> UploadFileAsync(string fileNa
return NullableUtils.Unwrap(uploadedFiles.Entries)[0];
}

[TestMethod]
public async System.Threading.Tasks.Task TestGetFileThumbnailUrl() {
string thumbnailFileName = Utils.GetUUID();
System.IO.Stream thumbnailContentStream = Utils.GenerateByteStream(size: 1024 * 1024);
FileFull thumbnailFile = await UploadFileAsync(fileName: thumbnailFileName, fileStream: thumbnailContentStream);
string downloadUrl = await client.Files.GetFileThumbnailUrlAsync(fileId: thumbnailFile.Id, extension: GetFileThumbnailUrlExtension.Png);
Assert.IsTrue(downloadUrl != null);
Assert.IsTrue(downloadUrl.Contains("https://"));
await client.Files.DeleteFileByIdAsync(fileId: thumbnailFile.Id);
}

[TestMethod]
public async System.Threading.Tasks.Task TestGetFileThumbnail() {
string thumbnailFileName = Utils.GetUUID();
Expand Down
2 changes: 1 addition & 1 deletion Box.Sdk.Gen/Box/JwtAuth/JwtConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public class JwtConfig {
/// </summary>
public string? UserId { get; init; }

internal JwtAlgorithm? Algorithm { get; }
internal JwtAlgorithm? Algorithm { get; init; } = JwtAlgorithm.Rs256;

public ITokenStorage TokenStorage { get; }

Expand Down
2 changes: 1 addition & 1 deletion Box.Sdk.Gen/Client/BoxClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ public BoxClient(IAuthentication auth, NetworkSession? networkSession = default)
public async System.Threading.Tasks.Task<FetchResponse> MakeRequestAsync(FetchOptions fetchOptions) {
IAuthentication auth = fetchOptions.Auth == null ? this.Auth : NullableUtils.Unwrap(fetchOptions.Auth);
NetworkSession networkSession = fetchOptions.NetworkSession == null ? this.NetworkSession : NullableUtils.Unwrap(fetchOptions.NetworkSession);
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 };
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 };
return await networkSession.NetworkClient.FetchAsync(options: enrichedFetchOptions).ConfigureAwait(false);
}

Expand Down
37 changes: 37 additions & 0 deletions Box.Sdk.Gen/Managers/Downloads/DownloadsManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,43 @@ public class DownloadsManager : IDownloadsManager {
public DownloadsManager(NetworkSession? networkSession = default) {
NetworkSession = networkSession ?? new NetworkSession();
}
/// <summary>
/// Returns the contents of a file in binary format.
/// </summary>
/// <param name="fileId">
/// The unique identifier that represents a file.
///
/// The ID for any file can be determined
/// by visiting a file in the web application
/// and copying the ID from the URL. For example,
/// for the URL `https://*.app.box.com/files/123`
/// the `file_id` is `123`.
/// Example: "12345"
/// </param>
/// <param name="queryParams">
/// Query parameters of downloadFile method
/// </param>
/// <param name="headers">
/// Headers of downloadFile method
/// </param>
/// <param name="cancellationToken">
/// Token used for request cancellation.
/// </param>
public async System.Threading.Tasks.Task<string> GetDownloadFileUrlAsync(string fileId, GetDownloadFileUrlQueryParams? queryParams = default, GetDownloadFileUrlHeaders? headers = default, System.Threading.CancellationToken? cancellationToken = null) {
queryParams = queryParams ?? new GetDownloadFileUrlQueryParams();
headers = headers ?? new GetDownloadFileUrlHeaders();
Dictionary<string, string> queryParamsMap = Utils.PrepareParams(map: new Dictionary<string, string?>() { { "version", StringUtils.ToStringRepresentation(queryParams.Version) }, { "access_token", StringUtils.ToStringRepresentation(queryParams.AccessTokenField) } });
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));
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);
if (response.Headers.ContainsKey("location")) {
return response.Headers["location"];
}
if (response.Headers.ContainsKey("Location")) {
return response.Headers["Location"];
}
throw new BoxSdkException(message: "No location header in response");
}

/// <summary>
/// Returns the contents of a file in binary format.
/// </summary>
Expand Down
40 changes: 40 additions & 0 deletions Box.Sdk.Gen/Managers/Downloads/GetDownloadFileUrlHeaders.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using Box.Sdk.Gen;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Box.Sdk.Gen.Internal;
using Box.Sdk.Gen.Schemas;

namespace Box.Sdk.Gen.Managers {
public class GetDownloadFileUrlHeaders {
/// <summary>
/// The byte range of the content to download.
///
/// The format `bytes={start_byte}-{end_byte}` can be used to specify
/// what section of the file to download.
/// </summary>
public string? Range { get; init; }

/// <summary>
/// The URL, and optional password, for the shared link of this item.
///
/// This header can be used to access items that have not been
/// explicitly shared with a user.
///
/// Use the format `shared_link=[link]` or if a password is required then
/// use `shared_link=[link]&shared_link_password=[password]`.
///
/// This header can be used on the file or folder shared, as well as on any files
/// or folders nested within the item.
/// </summary>
public string? Boxapi { get; init; }

/// <summary>
/// Extra headers that will be included in the HTTP request.
/// </summary>
public Dictionary<string, string?> ExtraHeaders { get; }

public GetDownloadFileUrlHeaders(Dictionary<string, string?>? extraHeaders = default) {
ExtraHeaders = extraHeaders ?? new Dictionary<string, string?>() { };
}
}
}
24 changes: 24 additions & 0 deletions Box.Sdk.Gen/Managers/Downloads/GetDownloadFileUrlQueryParams.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using Box.Sdk.Gen;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Box.Sdk.Gen.Internal;
using Box.Sdk.Gen.Schemas;

namespace Box.Sdk.Gen.Managers {
public class GetDownloadFileUrlQueryParams {
/// <summary>
/// The file version to download
/// </summary>
public string? Version { get; init; }

/// <summary>
/// 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.
/// 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.
/// </summary>
public string? AccessTokenField { get; init; }

public GetDownloadFileUrlQueryParams() {

}
}
}
24 changes: 24 additions & 0 deletions Box.Sdk.Gen/Managers/Downloads/IDownloadsManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,30 @@ public interface IDownloadsManager {
/// <param name="cancellationToken">
/// Token used for request cancellation.
/// </param>
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.");

/// <summary>
/// Returns the contents of a file in binary format.
/// </summary>
/// <param name="fileId">
/// The unique identifier that represents a file.
///
/// The ID for any file can be determined
/// by visiting a file in the web application
/// and copying the ID from the URL. For example,
/// for the URL `https://*.app.box.com/files/123`
/// the `file_id` is `123`.
/// Example: "12345"
/// </param>
/// <param name="queryParams">
/// Query parameters of downloadFile method
/// </param>
/// <param name="headers">
/// Headers of downloadFile method
/// </param>
/// <param name="cancellationToken">
/// Token used for request cancellation.
/// </param>
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.");

}
Expand Down
50 changes: 50 additions & 0 deletions Box.Sdk.Gen/Managers/Files/FilesManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,56 @@ public async System.Threading.Tasks.Task<FileFull> CopyFileAsync(string fileId,
return SimpleJsonSerializer.Deserialize<FileFull>(NullableUtils.Unwrap(response.Data));
}

/// <summary>
/// Retrieves a thumbnail, or smaller image representation, of a file.
///
/// Sizes of `32x32`,`64x64`, `128x128`, and `256x256` can be returned in
/// the `.png` format and sizes of `32x32`, `160x160`, and `320x320`
/// can be returned in the `.jpg` format.
///
/// Thumbnails can be generated for the image and video file formats listed
/// [found on our community site][1].
///
/// [1]: https://community.box.com/t5/Migrating-and-Previewing-Content/File-Types-and-Fonts-Supported-in-Box-Content-Preview/ta-p/327
/// </summary>
/// <param name="fileId">
/// The unique identifier that represents a file.
///
/// The ID for any file can be determined
/// by visiting a file in the web application
/// and copying the ID from the URL. For example,
/// for the URL `https://*.app.box.com/files/123`
/// the `file_id` is `123`.
/// Example: "12345"
/// </param>
/// <param name="extension">
/// The file format for the thumbnail
/// Example: "png"
/// </param>
/// <param name="queryParams">
/// Query parameters of getFileThumbnailById method
/// </param>
/// <param name="headers">
/// Headers of getFileThumbnailById method
/// </param>
/// <param name="cancellationToken">
/// Token used for request cancellation.
/// </param>
public async System.Threading.Tasks.Task<string> GetFileThumbnailUrlAsync(string fileId, GetFileThumbnailUrlExtension extension, GetFileThumbnailUrlQueryParams? queryParams = default, GetFileThumbnailUrlHeaders? headers = default, System.Threading.CancellationToken? cancellationToken = null) {
queryParams = queryParams ?? new GetFileThumbnailUrlQueryParams();
headers = headers ?? new GetFileThumbnailUrlHeaders();
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) } });
Dictionary<string, string> headersMap = Utils.PrepareParams(map: DictionaryUtils.MergeDictionaries(new Dictionary<string, string?>() { }, headers.ExtraHeaders));
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);
if (response.Headers.ContainsKey("location")) {
return response.Headers["location"];
}
if (response.Headers.ContainsKey("Location")) {
return response.Headers["Location"];
}
throw new BoxSdkException(message: "No location header in response");
}

/// <summary>
/// Retrieves a thumbnail, or smaller image representation, of a file.
///
Expand Down
12 changes: 12 additions & 0 deletions Box.Sdk.Gen/Managers/Files/GetFileThumbnailUrlExtension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System.ComponentModel;
using Box.Sdk.Gen.Internal;
using Box.Sdk.Gen.Schemas;

namespace Box.Sdk.Gen.Managers {
public enum GetFileThumbnailUrlExtension {
[Description("png")]
Png,
[Description("jpg")]
Jpg
}
}
20 changes: 20 additions & 0 deletions Box.Sdk.Gen/Managers/Files/GetFileThumbnailUrlHeaders.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using Box.Sdk.Gen;
using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Box.Sdk.Gen.Internal;
using Box.Sdk.Gen.Schemas;

namespace Box.Sdk.Gen.Managers {
public class GetFileThumbnailUrlHeaders {
/// <summary>
/// Extra headers that will be included in the HTTP request.
/// </summary>
public Dictionary<string, string?> ExtraHeaders { get; }

public GetFileThumbnailUrlHeaders(Dictionary<string, string?>? extraHeaders = default) {
ExtraHeaders = extraHeaders ?? new Dictionary<string, string?>() { };
}
}
}
35 changes: 35 additions & 0 deletions Box.Sdk.Gen/Managers/Files/GetFileThumbnailUrlQueryParams.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using Box.Sdk.Gen;
using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Box.Sdk.Gen.Internal;
using Box.Sdk.Gen.Schemas;

namespace Box.Sdk.Gen.Managers {
public class GetFileThumbnailUrlQueryParams {
/// <summary>
/// The minimum height of the thumbnail
/// </summary>
public long? MinHeight { get; init; }

/// <summary>
/// The minimum width of the thumbnail
/// </summary>
public long? MinWidth { get; init; }

/// <summary>
/// The maximum height of the thumbnail
/// </summary>
public long? MaxHeight { get; init; }

/// <summary>
/// The maximum width of the thumbnail
/// </summary>
public long? MaxWidth { get; init; }

public GetFileThumbnailUrlQueryParams() {

}
}
}
37 changes: 37 additions & 0 deletions Box.Sdk.Gen/Managers/Files/IFilesManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,43 @@ public interface IFilesManager {
/// <param name="cancellationToken">
/// Token used for request cancellation.
/// </param>
public System.Threading.Tasks.Task<string> GetFileThumbnailUrlAsync(string fileId, GetFileThumbnailUrlExtension extension, GetFileThumbnailUrlQueryParams? queryParams = default, GetFileThumbnailUrlHeaders? headers = default, System.Threading.CancellationToken? cancellationToken = null) => throw new System.NotImplementedException("This method needs to be implemented by the derived class before calling it.");

/// <summary>
/// Retrieves a thumbnail, or smaller image representation, of a file.
///
/// Sizes of `32x32`,`64x64`, `128x128`, and `256x256` can be returned in
/// the `.png` format and sizes of `32x32`, `160x160`, and `320x320`
/// can be returned in the `.jpg` format.
///
/// Thumbnails can be generated for the image and video file formats listed
/// [found on our community site][1].
///
/// [1]: https://community.box.com/t5/Migrating-and-Previewing-Content/File-Types-and-Fonts-Supported-in-Box-Content-Preview/ta-p/327
/// </summary>
/// <param name="fileId">
/// The unique identifier that represents a file.
///
/// The ID for any file can be determined
/// by visiting a file in the web application
/// and copying the ID from the URL. For example,
/// for the URL `https://*.app.box.com/files/123`
/// the `file_id` is `123`.
/// Example: "12345"
/// </param>
/// <param name="extension">
/// The file format for the thumbnail
/// Example: "png"
/// </param>
/// <param name="queryParams">
/// Query parameters of getFileThumbnailById method
/// </param>
/// <param name="headers">
/// Headers of getFileThumbnailById method
/// </param>
/// <param name="cancellationToken">
/// Token used for request cancellation.
/// </param>
public System.Threading.Tasks.Task<System.IO.Stream?> GetFileThumbnailByIdAsync(string fileId, GetFileThumbnailByIdExtension extension, GetFileThumbnailByIdQueryParams? queryParams = default, GetFileThumbnailByIdHeaders? headers = default, System.Threading.CancellationToken? cancellationToken = null) => throw new System.NotImplementedException("This method needs to be implemented by the derived class before calling it.");

}
Expand Down
Loading
Loading