Skip to content

Commit 977f27a

Browse files
committed
[feature] download provided url into temp dir
1 parent 4e68a65 commit 977f27a

2 files changed

Lines changed: 192 additions & 10 deletions

File tree

src/main/java/com/evolvedbinary/bblValidator/controller/ValidateController.java

Lines changed: 68 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,40 +2,98 @@
22

33
import com.evolvedbinary.bblValidator.dto.ValidationForm;
44
import com.evolvedbinary.bblValidator.dto.ValidationResponse;
5+
import com.evolvedbinary.bblValidator.service.FileDownloadService;
56
import io.micronaut.http.MediaType;
67
import io.micronaut.http.annotation.Body;
78
import io.micronaut.http.annotation.Consumes;
89
import io.micronaut.http.annotation.Controller;
910
import io.micronaut.http.annotation.Post;
1011
import io.micronaut.http.annotation.QueryValue;
12+
import org.slf4j.Logger;
13+
import org.slf4j.LoggerFactory;
1114

15+
import java.io.IOException;
16+
import java.nio.file.Path;
17+
18+
/**
19+
* Controller for handling validation requests.
20+
*/
1221
@Controller("/validate")
1322
public class ValidateController {
1423

15-
// SCENARIO: Form URL Encoded
16-
// Matches when Content-Type is 'application/x-www-form-urlencoded'
24+
private static final Logger LOG = LoggerFactory.getLogger(ValidateController.class);
25+
private final FileDownloadService fileDownloadService;
26+
27+
/**
28+
* Constructor for ValidateController.
29+
*
30+
* @param fileDownloadService service for downloading files
31+
*/
32+
public ValidateController(FileDownloadService fileDownloadService) {
33+
this.fileDownloadService = fileDownloadService;
34+
}
35+
36+
/**
37+
* Handles form URL encoded validation requests.
38+
*
39+
* @param form validation form
40+
* @return validation response
41+
*/
1742
@Post
1843
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
1944
public ValidationResponse validateForm(@Body ValidationForm form) {
20-
return new ValidationResponse(form.schemaId(), form.url(), true, "form handler");
45+
try {
46+
Path downloadedFile = fileDownloadService.downloadToTemp(form.url());
47+
LOG.info("File downloaded to: {}", downloadedFile);
48+
// TODO: Perform validation with downloadedFile
49+
return new ValidationResponse(form.schemaId(), form.url(), true, "form handler");
50+
} catch (IOException e) {
51+
LOG.error("Failed to download file from URL: {}", form.url(), e);
52+
return new ValidationResponse(form.schemaId(), form.url(), false, "Download failed: " + e.getMessage());
53+
}
2154
}
2255

23-
// SCENARIO: CSV Body + Query param
24-
// Matches when Content-Type is 'text/csv'
56+
/**
57+
* Handles CSV body + query param validation requests.
58+
*
59+
* @param schemaId schema ID
60+
* @param csvContent CSV content
61+
* @return validation response
62+
*/
2563
@Post
2664
@Consumes(MediaType.TEXT_CSV)
2765
public ValidationResponse validateCsv(@QueryValue("schema-id") String schemaId,
2866
@Body String csvContent) {
29-
30-
return new ValidationResponse(schemaId, csvContent, true, "text handler");
67+
try {
68+
Path tempFile = fileDownloadService.saveContentToTemp(csvContent, "uploaded-content.csv");
69+
LOG.info("CSV content saved to: {}", tempFile);
70+
// TODO: Perform validation with tempFile
71+
return new ValidationResponse(schemaId, "CSV content", true, "text handler");
72+
} catch (IOException e) {
73+
LOG.error("Failed to save CSV content to temp file", e);
74+
return new ValidationResponse(schemaId, "CSV content", false, "Failed to save content: " + e.getMessage());
75+
}
3176
}
3277

33-
// SCENARIO: Query Params Only
34-
// We use ALL here as a fallback, but specific types above take precedence
78+
/**
79+
* Handles query params only validation requests.
80+
*
81+
* @param schemaId schema ID
82+
* @param url URL
83+
* @return validation response
84+
*/
3585
@Post
3686
@Consumes(MediaType.ALL)
3787
public ValidationResponse validateParams(@QueryValue("schema-id") String schemaId,
3888
@QueryValue String url) {
39-
return new ValidationResponse(schemaId, url, true, "query handler");
89+
try {
90+
Path downloadedFile = fileDownloadService.downloadToTemp(url);
91+
LOG.info("File downloaded to: {}", downloadedFile);
92+
// TODO: Perform validation with downloadedFile
93+
return new ValidationResponse(schemaId, url, true, "query handler");
94+
} catch (IOException e) {
95+
LOG.error("Failed to download file from URL: {}", url, e);
96+
return new ValidationResponse(schemaId, url, false, "Download failed: " + e.getMessage());
97+
}
4098
}
4199
}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
package com.evolvedbinary.bblValidator.service;
2+
3+
import jakarta.inject.Singleton;
4+
import org.slf4j.Logger;
5+
import org.slf4j.LoggerFactory;
6+
7+
import java.io.IOException;
8+
import java.io.InputStream;
9+
import java.net.URI;
10+
import java.net.http.HttpClient;
11+
import java.net.http.HttpRequest;
12+
import java.net.http.HttpResponse;
13+
import java.nio.file.Files;
14+
import java.nio.file.Path;
15+
import java.nio.file.StandardCopyOption;
16+
17+
@Singleton
18+
public class FileDownloadService {
19+
20+
private static final Logger LOG = LoggerFactory.getLogger(FileDownloadService.class);
21+
private static final String TEMP_DIR_PREFIX = "bbl-validator-";
22+
private static final String DEFAULT_FILENAME = "downloaded-file.csv";
23+
private final HttpClient httpClient;
24+
25+
public FileDownloadService() {
26+
this.httpClient = HttpClient.newBuilder()
27+
.followRedirects(HttpClient.Redirect.NORMAL)
28+
.build();
29+
}
30+
31+
/**
32+
* Downloads a file from the given URL and stores it in a temporary directory.
33+
*
34+
* @param url The URL to download from
35+
* @return Path to the downloaded file in the temp directory
36+
* @throws IOException if download or file operations fail
37+
* @throws IllegalArgumentException if url is null or empty
38+
*/
39+
public Path downloadToTemp(String url) throws IOException {
40+
try {
41+
Path tempDir = createTempDirectory();
42+
String filename = extractFilename(url);
43+
Path tempFile = tempDir.resolve(filename);
44+
45+
HttpRequest request = HttpRequest.newBuilder()
46+
.uri(URI.create(url))
47+
.GET()
48+
.build();
49+
50+
HttpResponse<InputStream> response = httpClient.send(
51+
request,
52+
HttpResponse.BodyHandlers.ofInputStream()
53+
);
54+
55+
try (InputStream inputStream = response.body()) {
56+
Files.copy(inputStream, tempFile, StandardCopyOption.REPLACE_EXISTING);
57+
}
58+
59+
LOG.info("Downloaded file from {} to {}", url, tempFile);
60+
return tempFile;
61+
62+
} catch (InterruptedException e) {
63+
Thread.currentThread().interrupt();
64+
throw new IOException("Download interrupted for URL: " + url, e);
65+
}
66+
}
67+
68+
/**
69+
* Saves content to a temporary file.
70+
*
71+
* @param content The content to save
72+
* @param filename The filename to use
73+
* @return Path to the created temp file
74+
* @throws IOException if file operations fail
75+
* @throws IllegalArgumentException if content or filename is null or empty
76+
*/
77+
public Path saveContentToTemp(String content, String filename) throws IOException {
78+
Path tempDir = createTempDirectory();
79+
Path tempFile = tempDir.resolve(filename);
80+
81+
Files.writeString(tempFile, content);
82+
83+
LOG.info("Saved content to temp file: {}", tempFile);
84+
return tempFile;
85+
}
86+
87+
/**
88+
* Creates a temporary directory with the standard prefix.
89+
*
90+
* @return Path to the created temp directory
91+
* @throws IOException if directory creation fails
92+
*/
93+
private Path createTempDirectory() throws IOException {
94+
return Files.createTempDirectory(TEMP_DIR_PREFIX);
95+
}
96+
97+
98+
/**
99+
* Extracts filename from URL or returns a default name.
100+
*
101+
* @param url The URL to extract filename from
102+
* @return The extracted filename or default filename
103+
*/
104+
private String extractFilename(String url) {
105+
try {
106+
String path = URI.create(url).getPath();
107+
if (path == null || path.isEmpty()) {
108+
return DEFAULT_FILENAME;
109+
}
110+
111+
int lastSlash = path.lastIndexOf('/');
112+
if (lastSlash >= 0 && lastSlash < path.length() - 1) {
113+
String filename = path.substring(lastSlash + 1);
114+
// Ensure filename is not empty after extraction
115+
if (!filename.trim().isEmpty()) {
116+
return filename;
117+
}
118+
}
119+
} catch (Exception e) {
120+
LOG.warn("Could not extract filename from URL: {}", url, e);
121+
}
122+
return DEFAULT_FILENAME;
123+
}
124+
}

0 commit comments

Comments
 (0)