 static long copyStreamContent(@Nullable ProgressIndicator indicator,
                                       @NotNull InputStream inputStream,
                                       @NotNull OutputStream outputStream,
                                       long expectedContentLength,
                                       boolean progressDescription) throws IOException, ProcessCanceledException {
    if (indicator != null) {
      indicator.checkCanceled();
      indicator.setIndeterminate(expectedContentLength <= 0);
    }
    CountingGZIPInputStream gzipStream = inputStream instanceof CountingGZIPInputStream ? (CountingGZIPInputStream)inputStream : null;
    byte[] buffer = new byte[StreamUtil.BUFFER_SIZE];
    int count;
    long bytesWritten = 0;
    long bytesRead = 0;
    long startTime = System.currentTimeMillis();
    while ((count = inputStream.read(buffer)) > 0) {
      outputStream.write(buffer, 0, count);
      bytesWritten += count;
      bytesRead = gzipStream != null ? gzipStream.getCompressedBytesRead() : bytesWritten;

      if (indicator != null) {
        indicator.checkCanceled();
        if (expectedContentLength > 0) {
          long currentTime = System.currentTimeMillis();
          if (currentTime > startTime) { // To not divide by zero
            long downloadSpeed = (bytesRead * 1000) / (currentTime - startTime); // B/s
            updateIndicator(indicator, downloadSpeed, bytesRead, expectedContentLength, progressDescription);
          }
        }
      }
    }
    if (gzipStream != null) {
      // Amount of read bytes may have changed when 'inputStream.read(buffer)' returns -1
      // E.g. reading GZIP trailer doesn't produce inflated stream data.
      bytesRead = gzipStream.getCompressedBytesRead();
      if (indicator != null && expectedContentLength > 0) {
        long currentTime = System.currentTimeMillis();
        if (currentTime > startTime) { // To not divide by zero
          long downloadSpeed = (bytesRead * 1000) / (currentTime - startTime); // B/s
          updateIndicator(indicator, downloadSpeed, bytesRead, expectedContentLength, progressDescription);
        }
      }
    }

    if (indicator != null) {
      indicator.checkCanceled();
    }

    if (bytesRead < expectedContentLength) {
      throw new IOException("Connection closed at byte " + bytesRead + ". Expected " + expectedContentLength + " bytes.");
    }

    return bytesWritten;
  }

  @A
 static long copyStreamContent(@Nullable ProgressIndicator indicator,
                                       @NotNull InputStream inputStream,
                                       @NotNull OutputStream outputStream,
                                       long expectedContentLength,
                                       boolean progressDescription) throw