#java #httpclient #java-11 #asynchttpclient #sendasync
#java #httpclient #java-11 #asynchttpclient #sendasync
Вопрос:
Я могу загрузить один медиафайл с помощью httpclient в java 11 следующим образом
public class Httptest {
private static HttpClient client = HttpClient.newBuilder().build();
public static void main(String[] args) throws Exception {
File fts = new File("P:/sample.ts"); //Destination of downloaded file
fts.createNewFile();
URI url = new URI("File url here"); //File Url
HttpRequest request = HttpRequest.newBuilder() //Creating HttpRequest using Builder class
.GET()
.uri(url)
.build();
Path file = Path.of("P:/samp.ts");
//BodyHandlers class has methods to handle the response body
// In this case, save it as a file (BodyHandlers.ofFile())
HttpResponse<Path> response = client.send(request,BodyHandlers.ofFile(file));
}
}
Приведенный выше фрагмент кода загружает файл .ts с URL-адреса. И он загружен правильно.
Теперь у меня есть список URL-адресов, List<URI> urls
. Я выполнил асинхронный вызов списка URL-адресов, а также обеспечил одновременные вызовы, добавив Executor service
. Я застрял в том, как записать список ответов в один файл.
Код, который я написал до сих пор:
public class httptest{
// Concurrent requests are made in 4 threads
private static ExecutorService executorService = Executors.newFixedThreadPool(4);
//HttpClient built along with executorservice
private static HttpClient client = HttpClient.newBuilder()
.executor(executorService)
.build();
public static void main(String[] args) throws Exception{
File fts = new File("P:/Spyder_directory/sample.ts");
fts.createNewFile();
List<URI> urls = Arrays.asList(
new URI("Url of file 1"),
new URI("Url of file 2"),
new URI("Url of file 3"),
new URI("Url of file 4"),
new URI("Url of file 5"));
List<HttpRequest> requests = urls.stream()
.map(HttpRequest::newBuilder)
.map(requestBuilder -> requestBuilder.build())
.collect(toList());
Path file = Path.of("P:/Spyder_directory/sample.ts");
List<CompletableFuture<HttpResponse<Path>>> results = requests.stream()
.map(individual_req -> client.sendAsync(individual_req,BodyHandlers.ofFile(file)))
.collect(Collectors.toList());
}
}
Файл sample.ts
, созданный в конце выполнения, не содержит ответа на сделанные запросы.
Если вы поняли суть моей проблемы, кто-нибудь может предложить альтернативные решения этой проблемы.
Ответ №1:
Одной из возможностей было бы использовать HttpResponse .BodyHandlers.ofByteArrayConsumer с помощью a Consumer<Optional<byte[]>>
, который записывает байты в файл. Это позволит вам контролировать, как открывается файл, позволяя добавлять к существующему файлу, а не создавать каждый раз новый файл.
Обратите внимание, что если вы это сделаете, вам не следует использовать sendAsync
, потому что запросы будут отправляться одновременно, и поэтому ответ тоже будет получен одновременно. Если вы все еще хотите отправлять запросы одновременно, вам нужно будет буферизировать ответы и наложить некоторую синхронизацию при их записи в файл.
Комментарии:
1. ДА. Спасибо за ответ, я допускал небольшие ошибки, когда речь шла об асинхронном и параллельном.
Consumer
исправлено.