如何在异步 httpclient java 11 中将多个异步 get 请求的响应写入单个文件?

How to write responses of multiple asynchronous get requests to a single file in asynchronous httpclient java 11?

提问人:vicki 提问时间:9/30/2020 更新时间:10/2/2020 访问量:580

问:

我可以像这样在 java 11 中使用 httpclient 下载单个媒体文件

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)); 
    }
}

上面的代码片段从 url 下载.ts文件。并且它被正确下载。

现在,我有 url 列表,.我对 url 列表进行了异步调用,并通过添加 . 我卡住的地方是,如何将响应列表写入单个文件。List<URI> urlsExecutor 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

java httpclient java-11 asynchttpclient sendasync

评论


答:

1赞 daniel 10/2/2020 #1

一种可能性是将 HttpResponse.BodyHandlers.ofByteArrayConsumer 与将字节写入文件的 a 一起使用。这样可以控制文件的打开方式,从而可以追加到现有文件,而不是每次都创建新文件。Consumer<Optional<byte[]>>

请注意,如果这样做,则不应使用,因为请求将同时发送,因此响应也将同时接收。如果您仍想同时发送请求,则需要缓冲响应,并在将它们写入文件时强制进行一些同步。sendAsync

评论

0赞 vicki 10/3/2020
是的。感谢您的回答,我在异步和并发方面犯了一些小错误。 修复了此问题。Consumer