1+ <# // Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. #>
2+ <#@ template debug="true" hostspecific="true" language="C#" #>
3+ <#@ include file="BaseModel.template.tt"#>
4+ <#@ output extension="\\" #>
5+ <#=writer.WriteHeader()#>
6+ package com.microsoft.graph.extensions;
7+
8+ import com.microsoft.graph.concurrency.ChunkedUploadResponseHandler;
9+ import com.microsoft.graph.core.ClientException;
10+ import com.microsoft.graph.core.GraphErrorCodes;
11+ import com.microsoft.graph.http.BaseRequest;
12+ import com.microsoft.graph.http.HttpMethod;
13+ import com.microsoft.graph.options.Option;
14+
15+ import java.util.List;
16+
17+ /**
18+ * The chunk upload request.
19+ */
20+ public class ChunkedUploadRequest {
21+
22+ /**
23+ * Content Range header name.
24+ */
25+ private static final String CONTENT_RANGE_HEADER_NAME = "Content-Range";
26+
27+ /**
28+ * Content Range value format.
29+ */
30+ private static final String CONTENT_RANGE_FORMAT = "bytes %1$d-%2$d/%3$d";
31+
32+ /**
33+ * The seconds for retry delay.
34+ */
35+ private static final int RETRY_DELAY = 2 * 1000;
36+
37+ /**
38+ * The chunk data sent to the server.
39+ */
40+ private final byte[] mData;
41+
42+ /**
43+ * The base request.
44+ */
45+ private final BaseRequest mBaseRequest;
46+
47+ /**
48+ * The max retry for single request.
49+ */
50+ private final int mMaxRetry;
51+
52+ /**
53+ * The retry counter.
54+ */
55+ private int mRetryCount;
56+
57+ /**
58+ * Construct the ChunkedUploadRequest
59+ *
60+ * @param requestUrl The upload url.
61+ * @param client The OneDrive client.
62+ * @param options The query options.
63+ * @param chunk The chunk byte array.
64+ * @param chunkSize The chunk array size.
65+ * @param maxRetry The limit on retry.
66+ * @param beginIndex The begin index of this chunk in the input stream.
67+ * @param totalLength The total length of the input stream.
68+ */
69+ public ChunkedUploadRequest(final String requestUrl,
70+ final IGraphServiceClient client,
71+ final List<Option> options,
72+ final byte[] chunk,
73+ final int chunkSize,
74+ final int maxRetry,
75+ final int beginIndex,
76+ final int totalLength) {
77+ this.mData = new byte[chunkSize];
78+ System.arraycopy(chunk, 0, this.mData, 0, chunkSize);
79+ this.mRetryCount = 0;
80+ this.mMaxRetry = maxRetry;
81+ this.mBaseRequest = new BaseRequest(requestUrl, client, options, ChunkedUploadResult.class) {
82+ };
83+ this.mBaseRequest.setHttpMethod(HttpMethod.PUT);
84+ this.mBaseRequest.addHeader(CONTENT_RANGE_HEADER_NAME,
85+ String.format(
86+ CONTENT_RANGE_FORMAT,
87+ beginIndex,
88+ beginIndex + chunkSize - 1,
89+ totalLength));
90+ }
91+
92+ /**
93+ * Upload a chunk with tries.
94+ *
95+ * @param responseHandler The handler handle http response.
96+ * @param <UploadType> The upload item type.
97+ * @return The upload result.
98+ */
99+ public <UploadType> ChunkedUploadResult upload(
100+ final ChunkedUploadResponseHandler<UploadType> responseHandler) {
101+ while (this.mRetryCount < this.mMaxRetry) {
102+ try {
103+ Thread.sleep(RETRY_DELAY * this.mRetryCount * this.mRetryCount);
104+ } catch (final InterruptedException e) {
105+ this.mBaseRequest.getClient().getLogger().logError("Exception while waiting upload file retry", e);
106+ }
107+
108+ ChunkedUploadResult result = null;
109+
110+ try {
111+ result = this.mBaseRequest
112+ .getClient()
113+ .getHttpProvider()
114+ .send(mBaseRequest, ChunkedUploadResult.class, this.mData, responseHandler);
115+ } catch (final ClientException e) {
116+ this.mBaseRequest.getClient().getLogger().logDebug("Request failed with, retry if necessary.");
117+ }
118+
119+ if (result != null && result.chunkCompleted()) {
120+ return result;
121+ }
122+
123+ this.mRetryCount++;
124+ }
125+
126+ return new ChunkedUploadResult(
127+ new ClientException("Upload session failed to many times.", null,
128+ GraphErrorCodes.UploadSessionIncomplete));
129+ }
130+ }
0 commit comments