@Override
    public InputStream read(final Path file, final TransferStatus status, final ConnectionCallback callback) throws BackgroundException {
        try {
            if(0L == status.getLength()) {
                return new NullInputStream(0L);
            }
            final Storage.Objects.Get request = session.getClient().objects().get(
                    containerService.getContainer(file).getName(), containerService.getKey(file));
            if(containerService.getContainer(file).attributes().getCustom().containsKey(GoogleStorageAttributesFinderFeature.KEY_REQUESTER_PAYS)) {
                request.setUserProject(session.getHost().getCredentials().getUsername());
            }
            final VersioningConfiguration versioning = null != session.getFeature(Versioning.class) ? session.getFeature(Versioning.class).getConfiguration(
                    containerService.getContainer(file)
            ) : VersioningConfiguration.empty();
            if(versioning.isEnabled()) {
                if(StringUtils.isNotBlank(file.attributes().getVersionId())) {
                    request.setGeneration(Long.parseLong(file.attributes().getVersionId()));
                }
            }
            if(status.isAppend()) {
                final HttpRange range = HttpRange.withStatus(status);
                final String header;
                if(TransferStatus.UNKNOWN_LENGTH == range.getEnd()) {
                    header = String.format("bytes=%d-", range.getStart());
                }
                else {
                    header = String.format("bytes=%d-%d", range.getStart(), range.getEnd());
                }
                if(log.isDebugEnabled()) {
                    log.debug(String.format("Add range header %s for file %s", header, file));
                }
                final HttpHeaders headers = request.getRequestHeaders();
                headers.setRange(header);
                // Disable compression
                headers.setAcceptEncoding("identity");
            }
            return request.executeMediaAsInputStream();
        }
        catch(IOException e) {
            throw new GoogleStorageExceptionMappingService().map("Download {0} failed", e, file);
        }
    }
@Test
    @Ignore
    public void testReadRangeUnknownLength() throws Exception {
        final Path container = new Path("cyberduck-test-eu", EnumSet.of(Path.Type.directory, Path.Type.volume));
        final Path test = new Path(container, String.format("%s %s", new AlphanumericRandomStringService().random(), new AlphanumericRandomStringService().random()), EnumSet.of(Path.Type.file));
        new GoogleStorageTouchFeature(session).touch(test, new TransferStatus());
        final byte[] content = RandomUtils.nextBytes(1023);
        final TransferStatus status = new TransferStatus().withLength(content.length);
        status.setChecksum(new SHA256ChecksumCompute().compute(new ByteArrayInputStream(content), status));
        final HttpResponseOutputStream<StorageObject> out = new GoogleStorageWriteFeature(session).write(test, status, new DisabledConnectionCallback());
        assertNotNull(out);
        new StreamCopier(new TransferStatus(), new TransferStatus()).transfer(new ByteArrayInputStream(content), out);
        test.attributes().setVersionId(String.valueOf(out.getStatus().getGeneration()));
        status.setAppend(true);
        status.setOffset(100L);
        status.setLength(-1L);
        final InputStream in = new GoogleStorageReadFeature(session).read(test, status, new DisabledConnectionCallback());
        assertNotNull(in);
        final ByteArrayOutputStream buffer = new ByteArrayOutputStream(content.length - 100);
        new StreamCopier(status, status).transfer(in, buffer);
        final byte[] reference = new byte[content.length - 100];
        System.arraycopy(content, 100, reference, 0, content.length - 100);
        assertArrayEquals(reference, buffer.toByteArray());
        in.close();
        new GoogleStorageDeleteFeature(session).delete(Collections.singletonList(test), new DisabledLoginCallback(), new Delete.DisabledCallback());
    }