Skip to content

Commit c2e84c1

Browse files
feat(boxsdkgen): Support chunk upload session plan API (box/box-openapi#616) (#1632)
1 parent 8ebf7c3 commit c2e84c1

11 files changed

Lines changed: 543 additions & 2 deletions

File tree

.codegen.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{ "engineHash": "04310d4", "specHash": "be75fa1", "version": "6.14.0" }
1+
{ "engineHash": "04310d4", "specHash": "88cd5aa", "version": "6.14.0" }

BoxSdkGen/BoxSdkGen.xcodeproj/project.pbxproj

Lines changed: 104 additions & 0 deletions
Large diffs are not rendered by default.

BoxSdkGen/Sources/Managers/ChunkedUploads/ChunkedUploadsManager.swift

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,47 @@ public class ChunkedUploadsManager {
188188
return try UploadParts.deserialize(from: response.data!)
189189
}
190190

191+
/// Using this method with urls provided in response when creating a new upload session is preferred to use over CreateFileUploadSessionPlan method.
192+
/// This allows to always upload your content to the closest Box data center and can significantly improve upload speed.
193+
/// Plan an upload session by checking which parts already exist on the server.
194+
/// This endpoint allows clients to optimize uploads by skipping parts that
195+
/// have already been uploaded (cache hits) and only uploading missing parts.
196+
///
197+
/// The actual endpoint URL is returned by the [`Create upload session`](e://post-files-upload-sessions)
198+
/// and [`Get upload session`](e://get-files-upload-sessions-id) endpoints.
199+
///
200+
/// - Parameters:
201+
/// - url: URL of createFileUploadSessionPlan method
202+
/// - requestBody: Request body of createFileUploadSessionPlan method
203+
/// - headers: Headers of createFileUploadSessionPlan method
204+
/// - Returns: The `UploadSessionPlanResponse`.
205+
/// - Throws: The `GeneralError`.
206+
public func createFileUploadSessionPlanByUrl(url: String, requestBody: UploadSessionPlanRequest, headers: CreateFileUploadSessionPlanByUrlHeaders = CreateFileUploadSessionPlanByUrlHeaders()) async throws -> UploadSessionPlanResponse {
207+
let headersMap: [String: String] = Utils.Dictionary.prepareParams(map: Utils.Dictionary.merge([:], headers.extraHeaders))
208+
let response: FetchResponse = try await self.networkSession.networkClient.fetch(options: FetchOptions(url: url, method: "POST", headers: headersMap, data: try requestBody.serialize(), contentType: "application/json", responseFormat: ResponseFormat.json, auth: self.auth, networkSession: self.networkSession))
209+
return try UploadSessionPlanResponse.deserialize(from: response.data!)
210+
}
211+
212+
/// Plan an upload session by checking which parts already exist on the server.
213+
/// This endpoint allows clients to optimize uploads by skipping parts that
214+
/// have already been uploaded (cache hits) and only uploading missing parts.
215+
///
216+
/// The actual endpoint URL is returned by the [`Create upload session`](e://post-files-upload-sessions)
217+
/// and [`Get upload session`](e://get-files-upload-sessions-id) endpoints.
218+
///
219+
/// - Parameters:
220+
/// - uploadSessionId: The ID of the upload session.
221+
/// Example: "D5E3F7A"
222+
/// - requestBody: Request body of createFileUploadSessionPlan method
223+
/// - headers: Headers of createFileUploadSessionPlan method
224+
/// - Returns: The `UploadSessionPlanResponse`.
225+
/// - Throws: The `GeneralError`.
226+
public func createFileUploadSessionPlan(uploadSessionId: String, requestBody: UploadSessionPlanRequest, headers: CreateFileUploadSessionPlanHeaders = CreateFileUploadSessionPlanHeaders()) async throws -> UploadSessionPlanResponse {
227+
let headersMap: [String: String] = Utils.Dictionary.prepareParams(map: Utils.Dictionary.merge([:], headers.extraHeaders))
228+
let response: FetchResponse = try await self.networkSession.networkClient.fetch(options: FetchOptions(url: "\(self.networkSession.baseUrls.uploadUrl)\("/2.0/files/upload_sessions/")\(Utils.Strings.toString(value: uploadSessionId)!)\("/plan")", method: "POST", headers: headersMap, data: try requestBody.serialize(), contentType: "application/json", responseFormat: ResponseFormat.json, auth: self.auth, networkSession: self.networkSession))
229+
return try UploadSessionPlanResponse.deserialize(from: response.data!)
230+
}
231+
191232
/// Using this method with urls provided in response when creating a new upload session is preferred to use over CreateFileUploadSessionCommit method.
192233
/// This allows to always upload your content to the closest Box data center and can significantly improve upload speed.
193234
/// Close an upload session and create a file from the uploaded chunks.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import Foundation
2+
3+
public class CreateFileUploadSessionPlanByUrlHeaders {
4+
/// Extra headers that will be included in the HTTP request.
5+
public let extraHeaders: [String: String?]?
6+
7+
/// Initializer for a CreateFileUploadSessionPlanByUrlHeaders.
8+
///
9+
/// - Parameters:
10+
/// - extraHeaders: Extra headers that will be included in the HTTP request.
11+
public init(extraHeaders: [String: String?]? = [:]) {
12+
self.extraHeaders = extraHeaders
13+
}
14+
15+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import Foundation
2+
3+
public class CreateFileUploadSessionPlanHeaders {
4+
/// Extra headers that will be included in the HTTP request.
5+
public let extraHeaders: [String: String?]?
6+
7+
/// Initializer for a CreateFileUploadSessionPlanHeaders.
8+
///
9+
/// - Parameters:
10+
/// - extraHeaders: Extra headers that will be included in the HTTP request.
11+
public init(extraHeaders: [String: String?]? = [:]) {
12+
self.extraHeaders = extraHeaders
13+
}
14+
15+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import Foundation
2+
3+
/// Represents a planned upload part with `SHA-512` hash
4+
/// for upload session planning.
5+
public class UploadPartPlan: Codable, RawJSONReadable {
6+
private enum CodingKeys: String, CodingKey {
7+
case offset
8+
case size
9+
case sha512
10+
}
11+
12+
/// Internal backing store for rawData. Used to store raw dictionary data associated with the instance.
13+
private var _rawData: [String: Any]?
14+
15+
/// Returns the raw dictionary data associated with the instance. This is a read-only property.
16+
public var rawData: [String: Any]? {
17+
return _rawData
18+
}
19+
20+
21+
/// The offset of the chunk within the file
22+
/// in bytes. The lower bound of the position
23+
/// of the chunk within the file.
24+
public let offset: Int64
25+
26+
/// The size of the chunk in bytes.
27+
public let size: Int64
28+
29+
/// The `SHA-512` hash of the chunk.
30+
public let sha512: String
31+
32+
/// Initializer for a UploadPartPlan.
33+
///
34+
/// - Parameters:
35+
/// - offset: The offset of the chunk within the file
36+
/// in bytes. The lower bound of the position
37+
/// of the chunk within the file.
38+
/// - size: The size of the chunk in bytes.
39+
/// - sha512: The `SHA-512` hash of the chunk.
40+
public init(offset: Int64, size: Int64, sha512: String) {
41+
self.offset = offset
42+
self.size = size
43+
self.sha512 = sha512
44+
}
45+
46+
required public init(from decoder: Decoder) throws {
47+
let container = try decoder.container(keyedBy: CodingKeys.self)
48+
offset = try container.decode(Int64.self, forKey: .offset)
49+
size = try container.decode(Int64.self, forKey: .size)
50+
sha512 = try container.decode(String.self, forKey: .sha512)
51+
}
52+
53+
public func encode(to encoder: Encoder) throws {
54+
var container = encoder.container(keyedBy: CodingKeys.self)
55+
try container.encode(offset, forKey: .offset)
56+
try container.encode(size, forKey: .size)
57+
try container.encode(sha512, forKey: .sha512)
58+
}
59+
60+
/// Sets the raw JSON data.
61+
///
62+
/// - Parameters:
63+
/// - rawData: A dictionary containing the raw JSON data
64+
func setRawData(rawData: [String: Any]?) {
65+
self._rawData = rawData
66+
}
67+
68+
/// Gets the raw JSON data
69+
/// - Returns: The `[String: Any]?`.
70+
func getRawData() -> [String: Any]? {
71+
return self._rawData
72+
}
73+
74+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import Foundation
2+
3+
/// Represents a planned upload part that already exists
4+
/// on the server (cache hit).
5+
public class UploadPartPlanHit: Codable, RawJSONReadable {
6+
private enum CodingKeys: String, CodingKey {
7+
case offset
8+
case size
9+
case sha512
10+
case partId = "part_id"
11+
}
12+
13+
/// Internal backing store for rawData. Used to store raw dictionary data associated with the instance.
14+
private var _rawData: [String: Any]?
15+
16+
/// Returns the raw dictionary data associated with the instance. This is a read-only property.
17+
public var rawData: [String: Any]? {
18+
return _rawData
19+
}
20+
21+
22+
/// The offset of the chunk within the file
23+
/// in bytes. The lower bound of the position
24+
/// of the chunk within the file.
25+
public let offset: Int64
26+
27+
/// The size of the chunk in bytes.
28+
public let size: Int64
29+
30+
/// The `SHA-512` hash of the chunk.
31+
public let sha512: String
32+
33+
/// The unique ID of the chunk.
34+
public let partId: String
35+
36+
/// Initializer for a UploadPartPlanHit.
37+
///
38+
/// - Parameters:
39+
/// - offset: The offset of the chunk within the file
40+
/// in bytes. The lower bound of the position
41+
/// of the chunk within the file.
42+
/// - size: The size of the chunk in bytes.
43+
/// - sha512: The `SHA-512` hash of the chunk.
44+
/// - partId: The unique ID of the chunk.
45+
public init(offset: Int64, size: Int64, sha512: String, partId: String) {
46+
self.offset = offset
47+
self.size = size
48+
self.sha512 = sha512
49+
self.partId = partId
50+
}
51+
52+
required public init(from decoder: Decoder) throws {
53+
let container = try decoder.container(keyedBy: CodingKeys.self)
54+
offset = try container.decode(Int64.self, forKey: .offset)
55+
size = try container.decode(Int64.self, forKey: .size)
56+
sha512 = try container.decode(String.self, forKey: .sha512)
57+
partId = try container.decode(String.self, forKey: .partId)
58+
}
59+
60+
public func encode(to encoder: Encoder) throws {
61+
var container = encoder.container(keyedBy: CodingKeys.self)
62+
try container.encode(offset, forKey: .offset)
63+
try container.encode(size, forKey: .size)
64+
try container.encode(sha512, forKey: .sha512)
65+
try container.encode(partId, forKey: .partId)
66+
}
67+
68+
/// Sets the raw JSON data.
69+
///
70+
/// - Parameters:
71+
/// - rawData: A dictionary containing the raw JSON data
72+
func setRawData(rawData: [String: Any]?) {
73+
self._rawData = rawData
74+
}
75+
76+
/// Gets the raw JSON data
77+
/// - Returns: The `[String: Any]?`.
78+
func getRawData() -> [String: Any]? {
79+
return self._rawData
80+
}
81+
82+
}

BoxSdkGen/Sources/Schemas/UploadSession/UploadSessionSessionEndpointsField.swift

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import Foundation
22

33
public class UploadSessionSessionEndpointsField: Codable, RawJSONReadable {
44
private enum CodingKeys: String, CodingKey {
5+
case plan
56
case uploadPart = "upload_part"
67
case commit
78
case abort
@@ -19,6 +20,10 @@ public class UploadSessionSessionEndpointsField: Codable, RawJSONReadable {
1920
}
2021

2122

23+
/// The URL used to plan the upload session by checking which parts
24+
/// already exist on the server.
25+
public let plan: String?
26+
2227
/// The URL to upload parts to.
2328
public let uploadPart: String?
2429

@@ -40,13 +45,16 @@ public class UploadSessionSessionEndpointsField: Codable, RawJSONReadable {
4045
/// Initializer for a UploadSessionSessionEndpointsField.
4146
///
4247
/// - Parameters:
48+
/// - plan: The URL used to plan the upload session by checking which parts
49+
/// already exist on the server.
4350
/// - uploadPart: The URL to upload parts to.
4451
/// - commit: The URL used to commit the file.
4552
/// - abort: The URL for used to abort the session.
4653
/// - listParts: The URL users to list all parts.
4754
/// - status: The URL used to get the status of the upload.
4855
/// - logEvent: The URL used to get the upload log from.
49-
public init(uploadPart: String? = nil, commit: String? = nil, abort: String? = nil, listParts: String? = nil, status: String? = nil, logEvent: String? = nil) {
56+
public init(plan: String? = nil, uploadPart: String? = nil, commit: String? = nil, abort: String? = nil, listParts: String? = nil, status: String? = nil, logEvent: String? = nil) {
57+
self.plan = plan
5058
self.uploadPart = uploadPart
5159
self.commit = commit
5260
self.abort = abort
@@ -57,6 +65,7 @@ public class UploadSessionSessionEndpointsField: Codable, RawJSONReadable {
5765

5866
required public init(from decoder: Decoder) throws {
5967
let container = try decoder.container(keyedBy: CodingKeys.self)
68+
plan = try container.decodeIfPresent(String.self, forKey: .plan)
6069
uploadPart = try container.decodeIfPresent(String.self, forKey: .uploadPart)
6170
commit = try container.decodeIfPresent(String.self, forKey: .commit)
6271
abort = try container.decodeIfPresent(String.self, forKey: .abort)
@@ -67,6 +76,7 @@ public class UploadSessionSessionEndpointsField: Codable, RawJSONReadable {
6776

6877
public func encode(to encoder: Encoder) throws {
6978
var container = encoder.container(keyedBy: CodingKeys.self)
79+
try container.encodeIfPresent(plan, forKey: .plan)
7080
try container.encodeIfPresent(uploadPart, forKey: .uploadPart)
7181
try container.encodeIfPresent(commit, forKey: .commit)
7282
try container.encodeIfPresent(abort, forKey: .abort)
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import Foundation
2+
3+
/// Request body for planning an upload session.
4+
/// This allows checking which parts already exist
5+
/// on the server before uploading.
6+
public class UploadSessionPlanRequest: Codable, RawJSONReadable {
7+
private enum CodingKeys: String, CodingKey {
8+
case parts
9+
}
10+
11+
/// Internal backing store for rawData. Used to store raw dictionary data associated with the instance.
12+
private var _rawData: [String: Any]?
13+
14+
/// Returns the raw dictionary data associated with the instance. This is a read-only property.
15+
public var rawData: [String: Any]? {
16+
return _rawData
17+
}
18+
19+
20+
/// The list of parts to check for existence.
21+
public let parts: [UploadPartPlan]
22+
23+
/// Initializer for a UploadSessionPlanRequest.
24+
///
25+
/// - Parameters:
26+
/// - parts: The list of parts to check for existence.
27+
public init(parts: [UploadPartPlan]) {
28+
self.parts = parts
29+
}
30+
31+
required public init(from decoder: Decoder) throws {
32+
let container = try decoder.container(keyedBy: CodingKeys.self)
33+
parts = try container.decode([UploadPartPlan].self, forKey: .parts)
34+
}
35+
36+
public func encode(to encoder: Encoder) throws {
37+
var container = encoder.container(keyedBy: CodingKeys.self)
38+
try container.encode(parts, forKey: .parts)
39+
}
40+
41+
/// Sets the raw JSON data.
42+
///
43+
/// - Parameters:
44+
/// - rawData: A dictionary containing the raw JSON data
45+
func setRawData(rawData: [String: Any]?) {
46+
self._rawData = rawData
47+
}
48+
49+
/// Gets the raw JSON data
50+
/// - Returns: The `[String: Any]?`.
51+
func getRawData() -> [String: Any]? {
52+
return self._rawData
53+
}
54+
55+
}

0 commit comments

Comments
 (0)