@Override
    public HttpResponseOutputStream<File> write(final Path file, final TransferStatus status, final ConnectionCallback callback) throws BackgroundException {
        final DelayedHttpEntityCallable<File> command = new DelayedHttpEntityCallable<File>(file) {
            @Override
            public File call(final HttpEntity entity) throws BackgroundException {
                // Initiate a resumable upload
                String location;
                try {
                    location = start(file, status);
                }
                catch(InteroperabilityException e) {
                    if(null == status.getLockId()) {
                        throw e;
                    }
                    location = start(file, status.withLockId(null));
                }
                final StoregateApiClient client = session.getClient();
                try {
                    // Upload the file
                    final HttpPut put = new HttpPut(location);
                    put.setEntity(entity);
                    final String header;
                    if(status.getLength() == 0) {
                        // Touch
                        header = "*/0";
                    }
                    else {
                        final HttpRange range = HttpRange.byLength(0, status.getLength());
                        header = String.format("%d-%d/%d", range.getStart(), range.getEnd(), status.getLength());
                    }
                    put.addHeader(HttpHeaders.CONTENT_RANGE, String.format("bytes %s", header));
                    final HttpResponse putResponse = client.getClient().execute(put);
                    try {
                        switch(putResponse.getStatusLine().getStatusCode()) {
                            case HttpStatus.SC_OK:
                            case HttpStatus.SC_CREATED:
                                final File result = new JSON().getContext(FileMetadata.class).readValue(
                                        new InputStreamReader(putResponse.getEntity().getContent(), StandardCharsets.UTF_8),
                                        File.class);
                                fileid.cache(file, result.getId());
                                return result;
                            default:
                                throw new StoregateExceptionMappingService(fileid).map("Upload {0} failed",
                                        new ApiException(putResponse.getStatusLine().getStatusCode(), putResponse.getStatusLine().getReasonPhrase(), Collections.emptyMap(),
                                                EntityUtils.toString(putResponse.getEntity())), file);
                        }
                    }
                    catch(BackgroundException e) {
                        // Cancel upload on error reply
                        cancel(file, location);
                        throw e;
                    }
                    finally {
                        EntityUtils.consume(putResponse.getEntity());
                    }
                }
                catch(IOException e) {
                    // Cancel upload on I/O failure
                    cancel(file, location);
                    throw new HttpExceptionMappingService().map("Upload {0} failed", e, file);
                }
            }

            @Override
            public long getContentLength() {
                return status.getLength();
            }
        };
        return this.write(file, status, command);
    }
@Test
    public void testWriteSingleByte() throws Exception {
        final StoregateIdProvider nodeid = new StoregateIdProvider(session);
        final StoregateWriteFeature feature = new StoregateWriteFeature(session, nodeid);
        final Path room = new StoregateDirectoryFeature(session, nodeid).mkdir(
                new Path(String.format("/My files/%s", new AlphanumericRandomStringService().random()),
                        EnumSet.of(Path.Type.directory, Path.Type.volume)), new TransferStatus());
        final byte[] content = RandomUtils.nextBytes(1);
        final TransferStatus status = new TransferStatus();
        status.setLength(content.length);
        final Path file = new Path(room, new AlphanumericRandomStringService().random(), EnumSet.of(Path.Type.file));
        final HttpResponseOutputStream<File> out = feature.write(file, status, new DisabledConnectionCallback());
        final ByteArrayInputStream in = new ByteArrayInputStream(content);
        assertEquals(content.length, IOUtils.copyLarge(in, out));
        in.close();
        out.close();
        assertNotNull(out.getStatus());
        assertTrue(new DefaultFindFeature(session).find(file));
        final byte[] compare = new byte[content.length];
        final InputStream stream = new StoregateReadFeature(session, nodeid).read(file, new TransferStatus().withLength(content.length), new DisabledConnectionCallback());
        IOUtils.readFully(stream, compare);
        stream.close();
        assertArrayEquals(content, compare);
        new StoregateDeleteFeature(session, nodeid).delete(Collections.singletonList(file), new DisabledLoginCallback(), new Delete.DisabledCallback());
    }