code: private void putObject() throws IOException {
      LOG.debug("Executing regular upload for {}", writeOperationHelper);
  
      final COSDataBlocks.DataBlock block = getActiveBlock();
      int size = block.dataSize();
      final COSDataBlocks.BlockUploadData uploadData = block.startUpload();
      final PutObjectRequest putObjectRequest = uploadData.hasFile()
          ? writeOperationHelper.newPutRequest(uploadData.getFile())
          : writeOperationHelper.newPutRequest(uploadData.getUploadStream(), size);
  
      final ObjectMetadata om = new ObjectMetadata();
      om.setUserMetadata(mMetadata);
      if (contentType != null && !contentType.isEmpty()) {
        om.setContentType(contentType);
      } else {
        om.setContentType("application/octet-stream");
      }
      putObjectRequest.setMetadata(om);
      ListenableFuture<PutObjectResult> putObjectResult =
          executorService.submit(new Callable<PutObjectResult>() {
            @Override
            public PutObjectResult call() throws Exception {
              PutObjectResult result;
              try {
                // the putObject call automatically closes the input
                // stream afterwards.
                result = writeOperationHelper.putObject(putObjectRequest);
              } finally {
                closeAll(LOG, uploadData, block);
              }
              return result;
            }
          });
      clearActiveBlock();
      // wait for completion
      try {
        putObjectResult.get();
      } catch (InterruptedException ie) {
        LOG.warn("Interrupted object upload", ie);
        Thread.currentThread().interrupt();
      } catch (ExecutionException ee) {
        throw extractException("regular upload", key, ee);
      }
    }
docs: Upload the current block as a single PUT request; if the buffer is empty a
  0-byte PUT will be invoked, as it is needed to create an entry at the far
  end.
  
  @throws IOException any problem