import java.io.*;
import java.net.http.*;
import java.util.*;
import com.fasterxml.jackson.databind.ObjectMapper;
public class LiltUploadClient {
private final String apiKey;
private final String baseUrl;
private final HttpClient httpClient;
private final ObjectMapper objectMapper;
public LiltUploadClient(String apiKey, String baseUrl) {
this.apiKey = apiKey;
this.baseUrl = baseUrl != null ? baseUrl : "https://lilt.com/v2";
this.httpClient = HttpClient.newHttpClient();
this.objectMapper = new ObjectMapper();
}
public void uploadFile(String filePath, String filename, String contentType) throws Exception {
byte[] fileData = Files.readAllBytes(Paths.get(filePath));
// 1. Initiate upload
Map<String, Object> uploadRequest = new HashMap<>();
uploadRequest.put("filename", filename);
uploadRequest.put("type", contentType);
Map<String, Object> metadata = new HashMap<>();
metadata.put("size", fileData.length);
uploadRequest.put("metadata", metadata);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(baseUrl + "/upload/s3/params"))
.header("Authorization", "Bearer " + apiKey)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(objectMapper.writeValueAsString(uploadRequest)))
.build();
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() != 200) {
throw new RuntimeException("Failed to initiate upload: " + response.body());
}
Map<String, Object> uploadParams = objectMapper.readValue(response.body(), Map.class);
// 2. Upload to S3
HttpRequest.Builder uploadRequestBuilder = HttpRequest.newBuilder()
.uri(URI.create((String) uploadParams.get("url")))
.header("Content-Type", contentType)
.PUT(HttpRequest.BodyPublishers.ofByteArray(fileData));
// Add any additional headers
Map<String, String> headers = (Map<String, String>) uploadParams.get("headers");
if (headers != null) {
headers.forEach(uploadRequestBuilder::header);
}
HttpRequest uploadRequest = uploadRequestBuilder.build();
HttpResponse<String> uploadResponse = httpClient.send(uploadRequest, HttpResponse.BodyHandlers.ofString());
if (uploadResponse.statusCode() != 200) {
throw new RuntimeException("Failed to upload file: " + uploadResponse.body());
}
System.out.println("Upload successful");
}
public void uploadLargeFile(String filePath, String filename, String contentType) throws Exception {
File file = new File(filePath);
long fileSize = file.length();
int chunkSize = 5 * 1024 * 1024; // 5MB chunks
// 1. Initiate multipart upload
Map<String, Object> uploadRequest = new HashMap<>();
uploadRequest.put("filename", filename);
uploadRequest.put("type", contentType);
Map<String, Object> metadata = new HashMap<>();
metadata.put("size", fileSize);
uploadRequest.put("metadata", metadata);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(baseUrl + "/upload/s3/multipart"))
.header("Authorization", "Bearer " + apiKey)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(objectMapper.writeValueAsString(uploadRequest)))
.build();
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
Map<String, Object> initResponse = objectMapper.readValue(response.body(), Map.class);
String uploadId = (String) initResponse.get("uploadId");
String key = (String) initResponse.get("key");
List<Map<String, Object>> parts = new ArrayList<>();
// 2. Upload each part
try (FileInputStream fis = new FileInputStream(file)) {
byte[] buffer = new byte[chunkSize];
int partNumber = 1;
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
byte[] chunk = bytesRead == chunkSize ? buffer : Arrays.copyOf(buffer, bytesRead);
// Get presigned URL for this part
String partUrl = String.format("%s/upload/s3/multipart/%s/%d?s3Key=%s&size=%d",
baseUrl, uploadId, partNumber, key, chunk.length);
HttpRequest partRequest = HttpRequest.newBuilder()
.uri(URI.create(partUrl))
.header("Authorization", "Bearer " + apiKey)
.GET()
.build();
HttpResponse<String> partResponse = httpClient.send(partRequest, HttpResponse.BodyHandlers.ofString());
Map<String, Object> partParams = objectMapper.readValue(partResponse.body(), Map.class);
// Upload part
HttpRequest uploadPartRequest = HttpRequest.newBuilder()
.uri(URI.create((String) partParams.get("url")))
.header("Content-Type", contentType)
.PUT(HttpRequest.BodyPublishers.ofByteArray(chunk))
.build();
HttpResponse<String> uploadPartResponse = httpClient.send(uploadPartRequest, HttpResponse.BodyHandlers.ofString());
Map<String, Object> part = new HashMap<>();
part.put("ETag", uploadPartResponse.headers().firstValue("etag").orElse(""));
part.put("PartNumber", partNumber);
parts.add(part);
partNumber++;
}
}
// 3. Complete multipart upload
Map<String, Object> completeRequest = new HashMap<>();
completeRequest.put("parts", parts);
HttpRequest completeHttpRequest = HttpRequest.newBuilder()
.uri(URI.create(String.format("%s/upload/s3/multipart/%s/complete?s3Key=%s", baseUrl, uploadId, key)))
.header("Authorization", "Bearer " + apiKey)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(objectMapper.writeValueAsString(completeRequest)))
.build();
HttpResponse<String> completeResponse = httpClient.send(completeHttpRequest, HttpResponse.BodyHandlers.ofString());
if (completeResponse.statusCode() != 200) {
throw new RuntimeException("Failed to complete upload: " + completeResponse.body());
}
System.out.println("Multipart upload successful");
}
}
// Usage
LiltUploadClient client = new LiltUploadClient("your-api-key", null);
client.uploadFile("/path/to/file.pdf", "document.pdf", "application/pdf");