2121 * </ol>
2222 */
2323public class TusUploader {
24+ /**
25+ * Callback for upload progress events.
26+ */
27+ public interface ProgressListener {
28+ /**
29+ * Called when upload progress changes.
30+ * @param bytesSent Bytes accepted locally for the upload.
31+ * @param bytesTotal Total upload size.
32+ */
33+ void onProgress (long bytesSent , long bytesTotal );
34+ }
35+
36+ /**
37+ * Callback for accepted chunk events.
38+ */
39+ public interface ChunkCompleteListener {
40+ /**
41+ * Called after the server accepts an upload request.
42+ * @param chunkSize Bytes accepted by the completed request.
43+ * @param bytesAccepted Total bytes accepted by the server.
44+ * @param bytesTotal Total upload size.
45+ */
46+ void onChunkComplete (long chunkSize , long bytesAccepted , long bytesTotal );
47+ }
48+
2449 private URL uploadURL ;
2550 private Proxy proxy ;
2651 private TusInputStream input ;
@@ -30,6 +55,10 @@ public class TusUploader {
3055 private byte [] buffer ;
3156 private int requestPayloadSize = 10 * 1024 * 1024 ;
3257 private int bytesRemainingForRequest ;
58+ private long requestStartOffset ;
59+ private boolean requestProgressStarted ;
60+ private ProgressListener progressListener ;
61+ private ChunkCompleteListener chunkCompleteListener ;
3362
3463 private HttpURLConnection connection ;
3564 private OutputStream output ;
@@ -65,6 +94,8 @@ private void openConnection() throws IOException, ProtocolException {
6594 }
6695
6796 bytesRemainingForRequest = requestPayloadSize ;
97+ requestStartOffset = offset ;
98+ requestProgressStarted = false ;
6899 input .mark (requestPayloadSize );
69100
70101 if (proxy != null ) {
@@ -168,6 +199,24 @@ public int getRequestPayloadSize() {
168199 return requestPayloadSize ;
169200 }
170201
202+ /**
203+ * Set the listener used for upload progress events.
204+ *
205+ * @param listener Progress listener or null to disable events.
206+ */
207+ public void setProgressListener (ProgressListener listener ) {
208+ progressListener = listener ;
209+ }
210+
211+ /**
212+ * Set the listener used for accepted chunk events.
213+ *
214+ * @param listener Chunk-complete listener or null to disable events.
215+ */
216+ public void setChunkCompleteListener (ChunkCompleteListener listener ) {
217+ chunkCompleteListener = listener ;
218+ }
219+
171220 /**
172221 * Upload a part of the file by reading a chunk from the InputStream and writing
173222 * it to the HTTP request's body. If the number of available bytes is lower than the chunk's
@@ -184,6 +233,7 @@ public int getRequestPayloadSize() {
184233 */
185234 public int uploadChunk () throws IOException , ProtocolException {
186235 openConnection ();
236+ notifyProgressAtRequestStart ();
187237
188238 int bytesToRead = Math .min (getChunkSize (), bytesRemainingForRequest );
189239
@@ -201,6 +251,7 @@ public int uploadChunk() throws IOException, ProtocolException {
201251
202252 offset += bytesRead ;
203253 bytesRemainingForRequest -= bytesRead ;
254+ notifyProgress (offset );
204255
205256 if (bytesRemainingForRequest <= 0 ) {
206257 finishConnection ();
@@ -358,7 +409,28 @@ private void finishConnection() throws ProtocolException, IOException {
358409 connection );
359410 }
360411
412+ notifyChunkComplete (serverOffset - requestStartOffset , serverOffset );
361413 connection = null ;
414+ requestProgressStarted = false ;
415+ }
416+ }
417+
418+ private void notifyProgressAtRequestStart () {
419+ if (!requestProgressStarted ) {
420+ notifyProgress (offset );
421+ requestProgressStarted = true ;
422+ }
423+ }
424+
425+ private void notifyProgress (long bytesSent ) {
426+ if (progressListener != null ) {
427+ progressListener .onProgress (bytesSent , upload .getSize ());
428+ }
429+ }
430+
431+ private void notifyChunkComplete (long chunkSize , long bytesAccepted ) {
432+ if (chunkCompleteListener != null ) {
433+ chunkCompleteListener .onChunkComplete (chunkSize , bytesAccepted , upload .getSize ());
362434 }
363435 }
364436
0 commit comments