@Override
    public InputStream read(final Path file, final TransferStatus status, final ConnectionCallback callback) throws BackgroundException {
        try {
            if(file.getType().contains(Path.Type.upload)) {
                return new NullInputStream(0L);
            }
            if(status.isAppend()) {
                final HttpRange range = HttpRange.withStatus(status);
                return session.getClient().downloadFileRangeByIdToStream(
                    fileid.getVersionId(file),
                    range.getStart(), range.getEnd()
                );
            }
            final B2DownloadFileResponse response = session.getClient().downloadFileById(fileid.getVersionId(file));
            return new HttpMethodReleaseInputStream(response.getResponse(), status);
        }
        catch(B2ApiException e) {
            throw new B2ExceptionMappingService(fileid).map("Download {0} failed", e, file);
        }
        catch(IOException e) {
            throw new DefaultIOExceptionMappingService().map("Download {0} failed", e, file);
        }
    }
@Test
    public void testChangedNodeId() throws Exception {
        final B2VersionIdProvider fileid = new B2VersionIdProvider(session);
        final Path bucket = new B2DirectoryFeature(session, fileid).mkdir(
                new Path(new AlphanumericRandomStringService().random(), EnumSet.of(Path.Type.directory, Path.Type.volume)), new TransferStatus());
        final Path test = new B2TouchFeature(session, fileid).touch(new Path(bucket, new AlphanumericRandomStringService().random(), EnumSet.of(Path.Type.file)), new TransferStatus());
        final String latestnodeid = test.attributes().getVersionId();
        assertNotNull(latestnodeid);
        // Assume previously seen but changed on server
        final String invalidId = String.valueOf(RandomUtils.nextLong());
        test.attributes().setVersionId(invalidId);
        fileid.cache(test, invalidId);
        try {
            final InputStream in = new B2ReadFeature(session, fileid).read(test, new TransferStatus().withRemote(test.attributes()), new DisabledLoginCallback());
            fail();
        }
        catch(NotfoundException e) {
            //
        }
        assertNull(test.attributes().getVersionId());
        new B2DeleteFeature(session, fileid).delete(new B2ObjectListService(session, fileid).list(bucket, new DisabledListProgressListener()).toList(), new DisabledLoginCallback(), new Delete.DisabledCallback());
        new B2DeleteFeature(session, fileid).delete(Collections.singletonList(bucket), new DisabledLoginCallback(), new Delete.DisabledCallback());
    }