使用 httpurlconnection 传输文件时出现问题

问题描述 投票:0回答:1

将文件从预签名 URL (GET) 传输到另一个 URL (PUT) 时出现以下错误。当我并行调用我的 API 超过 3 次时,就会发生这种情况。

例如,如果我调用它10次。 3 传输将在 1 分钟内完成,然后在我的 POD 监控中 CPU 使用率将降至 0,15 分钟后我将收到错误。

    java.io.IOException: Error writing request body to server
at java.base/sun.net.www.protocol.http.HttpURLConnection$StreamingOutputStream.checkError(HttpURLConnection.java:3807)
at java.base/sun.net.www.protocol.http.HttpURLConnection$StreamingOutputStream.write(HttpURLConnection.java:3789)
...
at java.base/java.lang.Thread.run(Thread.java:833)
Suppressed: java.io.IOException: insufficient data written
    at java.base/sun.net.www.protocol.http.HttpURLConnection$StreamingOutputStream.close(HttpURLConnection.java:3834)
    at .....
    ... 3 more

我的方法:

public ResponseEntity<String> transferData(Config config) throws IOException {

var inputUrl = config.getInputdUrl();
var outputUrl = config.getOutputdUrl();


var uploadConnection = uploader.getUploadConnection(outputUrl);

try (var inputStream = downloader.getDownloadConnection(inputUrl).getInputStream(); 
     var outputStream = uploadConnection.getOutputStream()) {

    IOUtils.copyLarge(inputStream, outputStream);
    outputStream.flush();
    var resp = uploadConnection.getResponseCode();

    return ResponseEntity
            .status(HttpStatus.OK)
            .body("Transfer done with response:" + resp);
} catch (IOException ioe) {
    return ResponseEntity
            .status(HttpStatus.INTERNAL_SERVER_ERROR)
            .body("An  error occurred while transferring data : " + ioe);
}

}

我通过执行以下操作在 springboot 控制器中调用此方法:

            new Thread(() -> transferDataToScality(...)).start();
        return ResponseEntity.ok("Downloading data in asynchronous mode successfully started");

我怎样才能避免这个问题?

java http httpurlconnection
1个回答
0
投票

只要你还没有完成对uploadConnection的写入,就没有任何响应。 在检查响应代码之前关闭流:

try (var inputStream = downloader.getDownloadConnection(inputUrl).getInputStream(); 
     var outputStream = uploadConnection.getOutputStream()) {

    IOUtils.copyLarge(inputStream, outputStream);
} catch (IOException ioe) {
    return ResponseEntity
            .status(HttpStatus.INTERNAL_SERVER_ERROR)
            .body("An  error occurred while transferring data : " + ioe);
}

var resp = uploadConnection.getResponseCode();

return ResponseEntity
        .status(HttpStatus.OK)
        .body("Transfer done with response:" + resp);

注意我删除了对outputStream.flush()的调用。 不需要它,因为关闭 InputStream 或 OutputStream 总是会刷新它。

你也不需要像 IOUtils 这样的第三方类。 只需使用 transferTo:

try (var inputStream = downloader.getDownloadConnection(inputUrl).getInputStream(); 
     var outputStream = uploadConnection.getOutputStream()) {

    inputStream.transferTo(outputStream);
} catch (IOException ioe) {
© www.soinside.com 2019 - 2024. All rights reserved.