@Override
    public HttpResponseOutputStream<StorageObject> write(final Path file, final TransferStatus status, final ConnectionCallback callback) throws BackgroundException {
        final S3Object object = new S3WriteFeature(session, acl).getDetails(file, status);
        // ID for the initiated multipart upload.
        final MultipartUpload multipart;
        try {
            final Path bucket = containerService.getContainer(file);
            multipart = session.getClient().multipartStartUpload(
                    bucket.isRoot() ? StringUtils.EMPTY : bucket.getName(), object);
            if(log.isDebugEnabled()) {
                log.debug(String.format("Multipart upload started for %s with ID %s", multipart.getObjectKey(), multipart.getUploadId()));
            }
        }
        catch(ServiceException e) {
            throw new S3ExceptionMappingService().map("Upload {0} failed", e, file);
        }
        final MultipartOutputStream proxy = new MultipartOutputStream(multipart, file, status);
        return new HttpResponseOutputStream<StorageObject>(new MemorySegementingOutputStream(proxy,
                new HostPreferences(session.getHost()).getInteger("s3.upload.multipart.size")),
                new S3AttributesAdapter(session.getHost()), status) {
            @Override
            public StorageObject getStatus() {
                if(proxy.getResponse() != null) {
                    if(log.isDebugEnabled()) {
                        log.debug(String.format("Received response %s", proxy.getResponse()));
                    }
                    object.setContentLength(proxy.getOffset());
                    object.setETag(proxy.getResponse().getEtag());
                    if(proxy.getResponse().getVersionId() != null) {
                        object.addMetadata(S3Object.S3_VERSION_ID, proxy.getResponse().getVersionId());
                    }
                }
                return object;
            }
        };
    }
@Test
    public void testWrite() throws Exception {
        final S3MultipartWriteFeature feature = new S3MultipartWriteFeature(session, new S3AccessControlListFeature(session));
        final Path container = new Path("test-eu-central-1-cyberduck", EnumSet.of(Path.Type.directory, Path.Type.volume));
        final TransferStatus status = new TransferStatus();
        status.setLength(-1L);
        final Path file = new Path(container, UUID.randomUUID().toString(), EnumSet.of(Path.Type.file));
        final HttpResponseOutputStream<StorageObject> out = feature.write(file, status, new DisabledConnectionCallback());
        final byte[] content = RandomUtils.nextBytes(6 * 1024 * 1024);
        final ByteArrayInputStream in = new ByteArrayInputStream(content);
        final TransferStatus progress = new TransferStatus();
        final BytecountStreamListener count = new BytecountStreamListener();
        new StreamCopier(new TransferStatus(), progress).withListener(count).transfer(in, out);
        assertEquals(content.length, count.getSent());
        in.close();
        out.close();
        assertNotNull(out.getStatus());
        assertEquals(content.length, out.getStatus().getContentLength());
        assertTrue(new S3FindFeature(session, new S3AccessControlListFeature(session)).find(file));
        final PathAttributes attr = new S3AttributesFinderFeature(session, new S3AccessControlListFeature(session)).find(file);
        assertEquals(status.getResponse().getChecksum(), attr.getChecksum());
        assertEquals(content.length, attr.getSize());
        final byte[] compare = new byte[content.length];
        final InputStream stream = new S3ReadFeature(session).read(file, new TransferStatus().withLength(content.length), new DisabledConnectionCallback());
        IOUtils.readFully(stream, compare);
        stream.close();
        assertArrayEquals(content, compare);
        new S3DefaultDeleteFeature(session).delete(Collections.singletonList(file), new DisabledLoginCallback(), new Delete.DisabledCallback());
    }