### TusURLMemoryStore Example Source: https://context7.com/tus/tus-java-client/llms.txt Demonstrates using TusURLMemoryStore for session-based upload resuming. Upload URLs are stored in memory and lost on application termination. ```java import io.tus.java.client.*; import java.io.File; import java.net.URL; // Create memory store for session-based resuming TusURLMemoryStore memoryStore = new TusURLMemoryStore(); TusClient client = new TusClient(); client.setUploadCreationURL(new URL("https://tusd.tusdemo.net/files/")); client.enableResuming(memoryStore); // First upload attempt (simulating interruption) File file = new File("./large-file.bin"); TusUpload upload = new TusUpload(file); try { TusUploader uploader = client.resumeOrCreateUpload(upload); // Upload some chunks then simulate interruption for (int i = 0; i < 10; i++) { if (uploader.uploadChunk() == -1) break; } System.out.println("Partial upload at offset: " + uploader.getOffset()); uploader.finish(false); // Don't close stream for later resume } catch (Exception e) { System.err.println("Upload interrupted: " + e.getMessage()); } // Later: resume the same upload (within same session) try { TusUploader uploader = client.resumeOrCreateUpload(upload); System.out.println("Resumed at offset: " + uploader.getOffset()); while (uploader.uploadChunk() > -1) { // Continue uploading } uploader.finish(); } catch (Exception e) { e.printStackTrace(); } ``` -------------------------------- ### Implement File Upload with Progress Tracking Source: https://context7.com/tus/tus-java-client/llms.txt A complete example demonstrating how to use TusExecutor for robust uploads, including progress reporting and exponential backoff configuration. ```java import io.tus.java.client.*; import java.io.File; import java.io.IOException; import java.net.URL; public class TusUploadExample { public static void main(String[] args) { // Enable strict redirect handling for POST requests System.setProperty("http.strictPostRedirect", "true"); try { // Initialize client final TusClient client = new TusClient(); client.setUploadCreationURL(new URL("https://tusd.tusdemo.net/files/")); client.enableResuming(new TusURLMemoryStore()); client.enableRemoveFingerprintOnSuccess(); client.setConnectTimeout(10000); // Prepare upload File file = new File("./example/assets/prairie.jpg"); final TusUpload upload = new TusUpload(file); System.out.println("File: " + file.getName()); System.out.println("Size: " + upload.getSize() + " bytes"); System.out.println("Fingerprint: " + upload.getFingerprint()); // Execute with retry support TusExecutor executor = new TusExecutor() { @Override protected void makeAttempt() throws ProtocolException, IOException { TusUploader uploader = client.resumeOrCreateUpload(upload); uploader.setChunkSize(1024); // 1KB chunks for demo long lastProgressUpdate = 0; do { long totalBytes = upload.getSize(); long bytesUploaded = uploader.getOffset(); double progress = (double) bytesUploaded / totalBytes * 100; // Update progress every 10% if (progress - lastProgressUpdate >= 10) { System.out.printf("Upload progress: %06.2f%% (%d / %d bytes)\n", progress, bytesUploaded, totalBytes); lastProgressUpdate = (long) progress; } } while (uploader.uploadChunk() > -1); uploader.finish(); System.out.println("\nUpload completed successfully!"); System.out.println("File available at: " + uploader.getUploadURL()); } }; // Configure exponential backoff executor.setDelays(new int[]{500, 1000, 2000, 4000}); boolean success = executor.makeAttempts(); System.exit(success ? 0 : 1); } catch (Exception e) { System.err.println("Upload failed: " + e.getMessage()); e.printStackTrace(); System.exit(1); } } } ``` -------------------------------- ### Resume Existing Upload with TusClient Source: https://context7.com/tus/tus-java-client/llms.txt Attempts to continue a previously started upload by looking up its URL from the TusURLStore. Sends a HEAD request to determine the current offset and returns a TusUploader positioned at that offset. ```java import io.tus.java.client.*; import java.io.File; import java.net.URL; TusClient client = new TusClient(); client.setUploadCreationURL(new URL("https://tusd.tusdemo.net/files/")); client.enableResuming(new TusURLMemoryStore()); File file = new File("./large-backup.zip"); TusUpload upload = new TusUpload(file); try { // Attempt to resume an existing upload TusUploader uploader = client.resumeUpload(upload); System.out.println("Resuming upload from offset: " + uploader.getOffset()); // Continue uploading remaining chunks while (uploader.uploadChunk() > -1) { System.out.printf("Progress: %d / %d bytes\n", uploader.getOffset(), upload.getSize()); } uploader.finish(); System.out.println("Upload resumed and completed"); } catch (FingerprintNotFoundException e) { System.err.println("No previous upload found for fingerprint: " + upload.getFingerprint()); // Fall back to creating a new upload } catch (ResumingNotEnabledException e) { System.err.println("Resuming is not enabled - call client.enableResuming() first"); } catch (ProtocolException e) { System.err.println("Server error while resuming: " + e.getMessage()); } ``` -------------------------------- ### HEAD /resumeUpload Source: https://context7.com/tus/tus-java-client/llms.txt Attempts to continue a previously started upload by looking up its URL from the configured TusURLStore using the upload's fingerprint. ```APIDOC ## HEAD /resumeUpload ### Description The resumeUpload method attempts to continue a previously started upload by looking up its URL from the configured TusURLStore using the upload's fingerprint. It sends a HEAD request to determine the current offset and returns a TusUploader positioned at that offset. ### Method HEAD ### Parameters #### Request Body - **upload** (TusUpload) - Required - The upload object used to identify the previous session via fingerprint. ``` -------------------------------- ### Resume or Create Upload with TusClient Source: https://context7.com/tus/tus-java-client/llms.txt Combines resume and create logic: first attempts to resume an existing upload, and if no previous upload exists or resuming fails with a 404, it automatically creates a new upload. Recommended for most use cases. ```java import io.tus.java.client.*; import java.io.File; import java.net.URL; TusClient client = new TusClient(); client.setUploadCreationURL(new URL("https://tusd.tusdemo.net/files/")); client.enableResuming(new TusURLMemoryStore()); File file = new File("./important-data.tar.gz"); TusUpload upload = new TusUpload(file); try { // Automatically resume if possible, otherwise create new upload TusUploader uploader = client.resumeOrCreateUpload(upload); uploader.setChunkSize(512 * 1024); // 512KB chunks System.out.println("Starting/resuming from offset: " + uploader.getOffset()); int bytesUploaded; while ((bytesUploaded = uploader.uploadChunk()) > -1) { System.out.printf("Uploaded chunk: %d bytes, Total: %d / %d\n", bytesUploaded, uploader.getOffset(), upload.getSize()); } uploader.finish(); System.out.println("Upload available at: " + uploader.getUploadURL()); } catch (ProtocolException e) { System.err.println("Upload failed: " + e.getMessage()); } catch (java.io.IOException e) { System.err.println("Network error: " + e.getMessage()); } ``` -------------------------------- ### Configure TusClient for Uploads Source: https://context7.com/tus/tus-java-client/llms.txt Instantiate and configure TusClient for creating and resuming uploads. Set the server endpoint, enable resuming with a URL store, and configure timeouts, custom headers, and proxies. Check if resuming is enabled. ```java import io.tus.java.client.*; import java.net.URL; import java.net.Proxy; import java.util.HashMap; import java.util.Map; // Create and configure a TusClient instance TusClient client = new TusClient(); // Set the tus server endpoint for creating new uploads client.setUploadCreationURL(new URL("https://tusd.tusdemo.net/files/")); // Enable resuming uploads by providing a URL store client.enableResuming(new TusURLMemoryStore()); // Optionally clean up fingerprints after successful uploads client.enableRemoveFingerprintOnSuccess(); // Configure connection timeout (default is 5000ms) client.setConnectTimeout(10000); // Set custom HTTP headers for all requests (e.g., authentication) Map headers = new HashMap<>(); headers.put("Authorization", "Bearer your-api-token"); headers.put("X-Custom-Header", "custom-value"); client.setHeaders(headers); // Configure a proxy for all requests Proxy proxy = new Proxy(Proxy.Type.HTTP, new java.net.InetSocketAddress("proxy.example.com", 8080)); client.setProxy(proxy); // Check if resuming is enabled boolean canResume = client.resumingEnabled(); System.out.println("Resuming enabled: " + canResume); ``` -------------------------------- ### POST/HEAD /resumeOrCreateUpload Source: https://context7.com/tus/tus-java-client/llms.txt Combines resume and create logic: it first attempts to resume an existing upload, and if no previous upload exists, it automatically creates a new one. ```APIDOC ## POST/HEAD /resumeOrCreateUpload ### Description The resumeOrCreateUpload method combines resume and create logic: it first attempts to resume an existing upload, and if no previous upload exists or resuming fails with a 404, it automatically creates a new upload. This is the recommended method for most use cases. ### Method POST/HEAD ### Parameters #### Request Body - **upload** (TusUpload) - Required - The upload object to be processed. ``` -------------------------------- ### Configure Proxy for TusClient Source: https://github.com/tus/tus-java-client/blob/main/README.md Use this to route file uploads through a specific proxy server. Ensure the Proxy object is properly initialized before setting it on the client. ```java TusClient client = new TusClient(); Proxy myProxy = new Proxy(...); client.setProxy(myProxy); ``` -------------------------------- ### Custom SSL Configuration for TusClient Source: https://context7.com/tus/tus-java-client/llms.txt Extends TusClient to prepare connections with custom SSL settings, including custom certificate authorities and hostname verification. Requires a keystore file. ```java import io.tus.java.client.*; import javax.net.ssl.*; import java.net.HttpURLConnection; import java.net.URL; import java.security.KeyStore; import java.io.FileInputStream; public class SecureTusClient extends TusClient { private SSLSocketFactory sslSocketFactory; public SecureTusClient(String keystorePath, String keystorePassword) throws Exception { // Load custom keystore with trusted certificates KeyStore keyStore = KeyStore.getInstance("JKS"); keyStore.load(new FileInputStream(keystorePath), keystorePassword.toCharArray()); // Initialize TrustManager with custom keystore TrustManagerFactory tmf = TrustManagerFactory.getInstance( TrustManagerFactory.getDefaultAlgorithm()); tmf.init(keyStore); // Create SSL context SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, tmf.getTrustManagers(), null); this.sslSocketFactory = sslContext.getSocketFactory(); } @Override public void prepareConnection(HttpURLConnection connection) { super.prepareConnection(connection); if (connection instanceof HttpsURLConnection) { HttpsURLConnection secureConnection = (HttpsURLConnection) connection; secureConnection.setSSLSocketFactory(sslSocketFactory); // Optional: custom hostname verifier secureConnection.setHostnameVerifier((hostname, session) -> { return hostname.endsWith(".mycompany.com"); }); } } } // Usage SecureTusClient client = new SecureTusClient("/path/to/keystore.jks", "password"); client.setUploadCreationURL(new URL("https://secure-tus.mycompany.com/files/")); ``` -------------------------------- ### TusClient.beginOrResumeUploadFromURL Source: https://context7.com/tus/tus-java-client/llms.txt Initializes or resumes an upload session using a pre-existing URL, useful for services that do not support the Creation extension or for third-party API integrations. ```APIDOC ## TusClient.beginOrResumeUploadFromURL ### Description Allows uploading to a pre-existing upload URL obtained from an external service. This is useful when the tus server doesn't support the Creation extension or when the upload URL is provided by a third-party API. ### Parameters - **upload** (TusUpload) - Required - The upload object containing the file data. - **existingUploadUrl** (URL) - Required - The URL obtained from an external service. ### Response - **TusUploader** - Returns an uploader instance configured for the specified URL. ``` -------------------------------- ### POST /createUpload Source: https://context7.com/tus/tus-java-client/llms.txt Initiates a new upload on the tus server using the Creation extension by sending file size and metadata. ```APIDOC ## POST /createUpload ### Description Initiates a new upload on the tus server using the Creation extension. It sends a POST request to the upload creation URL with the file size and metadata, receives the upload URL in response, and returns a TusUploader ready for transferring data. ### Method POST ### Parameters #### Request Body - **upload** (TusUpload) - Required - The upload object containing file information and metadata. ``` -------------------------------- ### Implement Custom TusURLStore with Java Preferences Source: https://context7.com/tus/tus-java-client/llms.txt Create a custom TusURLStore implementation using Java Preferences API for persistent storage of upload resume URLs. This allows uploads to be resumed across application restarts. ```java import io.tus.java.client.TusURLStore; import java.net.URL; import java.net.MalformedURLException; import java.util.prefs.Preferences; // Custom persistent TusURLStore using Java Preferences API public class TusURLPreferencesStore implements TusURLStore { private final Preferences prefs; public TusURLPreferencesStore() { this.prefs = Preferences.userNodeForPackage(TusURLPreferencesStore.class); } @Override public void set(String fingerprint, URL url) { prefs.put(fingerprint, url.toString()); System.out.println("Stored URL for fingerprint: " + fingerprint); } @Override public URL get(String fingerprint) { String urlString = prefs.get(fingerprint, null); if (urlString == null) { return null; } try { return new URL(urlString); } catch (MalformedURLException e) { return null; } } @Override public void remove(String fingerprint) { prefs.remove(fingerprint); System.out.println("Removed URL for fingerprint: " + fingerprint); } } // Usage with custom store TusClient client = new TusClient(); client.setUploadCreationURL(new URL("https://tusd.tusdemo.net/files/")); client.enableResuming(new TusURLPreferencesStore()); client.enableRemoveFingerprintOnSuccess(); // Auto-cleanup after successful upload ``` -------------------------------- ### Create New Upload with TusClient Source: https://context7.com/tus/tus-java-client/llms.txt Initiates a new upload on the tus server. Requires the file size and metadata to be sent in a POST request. Returns a TusUploader ready for data transfer. ```java import io.tus.java.client.*; import java.io.File; import java.net.URL; TusClient client = new TusClient(); client.setUploadCreationURL(new URL("https://tusd.tusdemo.net/files/")); client.enableResuming(new TusURLMemoryStore()); File file = new File("./large-backup.zip"); TusUpload upload = new TusUpload(file); try { // Create a new upload on the server TusUploader uploader = client.createUpload(upload); System.out.println("Upload created at: " + uploader.getUploadURL()); // Upload in 1MB chunks uploader.setChunkSize(1024 * 1024); while (uploader.uploadChunk() > -1) { long uploaded = uploader.getOffset(); long total = upload.getSize(); System.out.printf("Progress: %.2f%%\n", (double) uploaded / total * 100); } uploader.finish(); System.out.println("Upload complete: " + uploader.getUploadURL()); } catch (ProtocolException e) { System.err.println("Protocol error: " + e.getMessage()); if (e.shouldRetry()) { System.err.println("This error is retryable"); } } catch (java.io.IOException e) { System.err.println("IO error: " + e.getMessage()); } ``` -------------------------------- ### Define TusUpload from File or InputStream Source: https://context7.com/tus/tus-java-client/llms.txt Create a TusUpload object either from a File (automatically setting size, stream, fingerprint, and filename metadata) or manually from an InputStream. Set custom metadata like filename, filetype, and description. Retrieve current metadata. ```java import io.tus.java.client.TusUpload; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.util.HashMap; import java.util.Map; // Create upload from a File (automatically sets size, stream, fingerprint, and filename metadata) File file = new File("/path/to/document.pdf"); TusUpload fileUpload = new TusUpload(file); System.out.println("File size: " + fileUpload.getSize() + " bytes"); System.out.println("Fingerprint: " + fileUpload.getFingerprint()); // Create upload manually from an InputStream InputStream inputStream = new FileInputStream("/path/to/video.mp4"); long streamSize = 52428800L; // 50 MB TusUpload streamUpload = new TusUpload(); streamUpload.setInputStream(inputStream); streamUpload.setSize(streamSize); streamUpload.setFingerprint("video-upload-unique-id-12345"); // Set custom metadata to be sent with the upload Map metadata = new HashMap<>(); metadata.put("filename", "video.mp4"); metadata.put("filetype", "video/mp4"); metadata.put("description", "Conference recording 2024"); streamUpload.setMetadata(metadata); // Retrieve current metadata Map currentMeta = streamUpload.getMetadata(); System.out.println("Metadata: " + currentMeta); ``` -------------------------------- ### Upload to Specific URL with tus-java-client Source: https://context7.com/tus/tus-java-client/llms.txt Use `beginOrResumeUploadFromURL` when the upload URL is provided by an external service or when the tus server lacks the Creation extension. Configure chunk size for large files like videos. ```java import io.tus.java.client.*; import java.io.File; import java.net.URL; TusClient client = new TusClient(); // URL obtained from external service (e.g., Vimeo API) URL existingUploadUrl = new URL("https://api.vimeo.com/me/videos/12345"); File file = new File("./video-project.mp4"); TusUpload upload = new TusUpload(file); try { // Begin or resume upload at the specified URL TusUploader uploader = client.beginOrResumeUploadFromURL(upload, existingUploadUrl); System.out.println("Server offset: " + uploader.getOffset()); // Set larger chunks for video uploads uploader.setChunkSize(5 * 1024 * 1024); // 5MB chunks while (uploader.uploadChunk() > -1) { double percent = (double) uploader.getOffset() / upload.getSize() * 100; System.out.printf("Uploading: %.1f%%\n", percent); } uploader.finish(); System.out.println("Video upload complete"); } catch (ProtocolException e) { System.err.println("Protocol error: " + e.getMessage()); } ``` -------------------------------- ### Perform Resumable Upload with tus-java-client Source: https://github.com/tus/tus-java-client/blob/main/README.md This snippet demonstrates how to configure and perform a resumable file upload using TusClient and TusExecutor. It covers setting the upload URL, enabling resuming, and handling the upload process with automatic retries. ```java TusClient client = new TusClient(); client.setUploadCreationURL(new URL("https://tusd.tusdemo.net/files")); client.enableResuming(new TusURLMemoryStore()); File file = new File("./cute_kitten.png"); final TusUpload upload = new TusUpload(file); TusExecutor executor = new TusExecutor() { @Override protected void makeAttempt() throws ProtocolException, IOException { TusUploader uploader = client.resumeOrCreateUpload(upload); uploader.setChunkSize(1024); do { long totalBytes = upload.getSize(); long bytesUploaded = uploader.getOffset(); double progress = (double) bytesUploaded / totalBytes * 100; System.out.printf("Upload at %06.2f%%.\n", progress); } while(uploader.uploadChunk() > -1); uploader.finish(); System.out.println("Upload finished."); System.out.format("Upload available at: %s", uploader.getUploadURL().toString()); } }; executor.makeAttempts(); ``` -------------------------------- ### Custom SSLSocketFactory in TusClient Source: https://github.com/tus/tus-java-client/blob/main/README.md Override the prepareConnection method in a TusClient subclass to provide a custom SSLSocketFactory for HTTPS connections. ```java @Override public void prepareConnection(@NotNull HttpURLConnection connection) { super.prepareConnection(connection); if(connection instanceof HttpsURLConnection) { HttpsURLConnection secureConnection = (HttpsURLConnection) connection; secureConnection.setSSLSocketFactory(mySSLSocketFactory); } } ``` -------------------------------- ### Implement Automatic Retries with TusExecutor Source: https://context7.com/tus/tus-java-client/llms.txt Wrap upload logic in makeAttempt() to leverage TusExecutor's automatic retry mechanism. Configure custom retry delays using setDelays(). ```java import io.tus.java.client.*; import java.io.File; import java.io.IOException; import java.net.URL; final TusClient client = new TusClient(); client.setUploadCreationURL(new URL("https://tusd.tusdemo.net/files/")); client.enableResuming(new TusURLMemoryStore()); File file = new File("./critical-backup.tar.gz"); final TusUpload upload = new TusUpload(file); // Create executor with custom retry logic TusExecutor executor = new TusExecutor() { @Override protected void makeAttempt() throws ProtocolException, IOException { TusUploader uploader = client.resumeOrCreateUpload(upload); uploader.setChunkSize(1024 * 1024); // 1MB chunks System.out.println("Attempt started at offset: " + uploader.getOffset()); while (uploader.uploadChunk() > -1) { double progress = (double) uploader.getOffset() / upload.getSize() * 100; System.out.printf("Progress: %.2f%%\n", progress); } uploader.finish(); System.out.println("Upload complete: " + uploader.getUploadURL()); } }; // Configure retry delays (default: 500ms, 1s, 2s, 3s) executor.setDelays(new int[]{1000, 2000, 4000, 8000, 16000}); // Exponential backoff try { // Execute with automatic retries boolean success = executor.makeAttempts(); if (success) { System.out.println("Upload succeeded"); } else { System.out.println("Upload was interrupted by user"); } } catch (ProtocolException e) { System.err.println("Upload failed after all retries: " + e.getMessage()); } catch (IOException e) { System.err.println("Network error after all retries: " + e.getMessage()); } ``` -------------------------------- ### Gradle Dependency for tus-java-client Source: https://github.com/tus/tus-java-client/blob/main/README.md Add this dependency to your Gradle project to include the tus-java-client library. ```groovy implementation 'io.tus.java.client:tus-java-client:0.5.1' ``` -------------------------------- ### Configure Chunk and Payload Size for Tus Uploads Source: https://context7.com/tus/tus-java-client/llms.txt Control upload performance and memory usage by setting `chunkSize` and `requestPayloadSize` on `TusUploader`. The `chunkSize` determines bytes read per `uploadChunk()` call, while `requestPayloadSize` limits the size of individual HTTP requests. ```java import io.tus.java.client.*; import java.io.File; import java.net.URL; TusClient client = new TusClient(); client.setUploadCreationURL(new URL("https://tusd.tusdemo.net/files/")); File file = new File("./dataset.csv"); TusUpload upload = new TusUpload(file); try { TusUploader uploader = client.createUpload(upload); // Configure chunk size (bytes read per uploadChunk() call) uploader.setChunkSize(256 * 1024); // 256KB chunks // Configure max payload per HTTP request (splits large uploads into multiple requests) // Default is 10MB; useful for memory-constrained environments uploader.setRequestPayloadSize(5 * 1024 * 1024); // 5MB per request System.out.println("Chunk size: " + uploader.getChunkSize()); System.out.println("Request payload size: " + uploader.getRequestPayloadSize()); System.out.println("Upload URL: " + uploader.getUploadURL()); long startTime = System.currentTimeMillis(); while (uploader.uploadChunk() > -1) { long elapsed = System.currentTimeMillis() - startTime; long bytesPerSec = uploader.getOffset() * 1000 / Math.max(elapsed, 1); System.out.printf("Offset: %d bytes, Speed: %d KB/s\n", uploader.getOffset(), bytesPerSec / 1024); } // Close connection and release resources uploader.finish(); // Alternative: finish without closing the input stream (for reuse) // uploader.finish(false); } catch (ProtocolException e) { System.err.println("Server rejected upload: " + e.getMessage()); } ``` -------------------------------- ### Maven Dependency for tus-java-client Source: https://github.com/tus/tus-java-client/blob/main/README.md Add this dependency to your Maven project to include the tus-java-client library. ```xml io.tus.java.client tus-java-client 0.5.1 ``` -------------------------------- ### TusUploader - Chunk Upload Handler Source: https://context7.com/tus/tus-java-client/llms.txt Manages the data transfer process, including chunk size configuration and request payload management for memory-constrained environments. ```APIDOC ## TusUploader ### Description Handles the actual data transfer in chunks. It manages HTTP PATCH connections, tracks upload offsets, and validates server responses. ### Methods - **setChunkSize(long size)** - Configures the number of bytes read per uploadChunk() call. - **setRequestPayloadSize(long size)** - Configures the maximum payload per HTTP request to control memory usage. - **uploadChunk()** - Performs the next chunk upload; returns -1 when complete. - **finish()** - Closes the connection and releases resources. ``` -------------------------------- ### Handle ProtocolException in tus-java-client Source: https://context7.com/tus/tus-java-client/llms.txt Use this pattern to catch protocol errors, inspect the underlying HTTP connection for debugging, and determine if an error is retryable. ```java import io.tus.java.client.*; import java.io.File; import java.net.URL; import java.net.HttpURLConnection; TusClient client = new TusClient(); client.setUploadCreationURL(new URL("https://tusd.tusdemo.net/files/")); try { TusUpload upload = new TusUpload(new File("./test.txt")); TusUploader uploader = client.createUpload(upload); while (uploader.uploadChunk() > -1) { // Upload chunks } uploader.finish(); } catch (ProtocolException e) { System.err.println("Protocol error: " + e.getMessage()); // Access the HTTP connection for detailed debugging HttpURLConnection conn = e.getCausingConnection(); if (conn != null) { try { int statusCode = conn.getResponseCode(); String statusMessage = conn.getResponseMessage(); System.err.printf("HTTP %d: %s\n", statusCode, statusMessage); // Check response headers String tusVersion = conn.getHeaderField("Tus-Resumable"); System.err.println("Server Tus-Version: " + tusVersion); } catch (Exception ex) { ex.printStackTrace(); } } // Check if this error is retryable (5XX or 423 status codes) if (e.shouldRetry()) { System.out.println("Error is retryable - consider using TusExecutor"); } else { System.out.println("Error is not retryable - check request parameters"); } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.