@Override
    public StorageObject upload(final Path file, final Local local, final BandwidthThrottle throttle,
                                final StreamListener listener, final TransferStatus status, final ConnectionCallback callback) throws BackgroundException {
        final S3Protocol.AuthenticationHeaderSignatureVersion signatureVersion = session.getSignatureVersion();
        switch(signatureVersion) {
            case AWS4HMACSHA256:
                if(!HashAlgorithm.sha256.equals(status.getChecksum().algorithm)) {
                    // Checksum not set in upload filter
                    status.setChecksum(writer.checksum(file, status).compute(local.getInputStream(), status));
                }
                break;
        }
        try {
            return super.upload(file, local, throttle, listener, status, callback);
        }
        catch(InteroperabilityException e) {
            if(!session.getSignatureVersion().equals(signatureVersion)) {
                // Retry if upload fails with Header "x-amz-content-sha256" set to the hex-encoded SHA256 hash of the
                // request payload is required for AWS Version 4 request signing
                return this.upload(file, local, throttle, listener, status, callback);
            }
            throw e;
        }
    }
@Test
    public void testUpload() throws Exception {
        final S3SingleUploadService service = new S3SingleUploadService(session, new S3WriteFeature(session, new S3AccessControlListFeature(session)));
        final Path container = new Path("test-eu-central-1-cyberduck", EnumSet.of(Path.Type.directory, Path.Type.volume));
        final String name = UUID.randomUUID() + ".txt";
        final Path test = new Path(container, name, EnumSet.of(Path.Type.file));
        final Local local = new Local(System.getProperty("java.io.tmpdir"), name);
        final byte[] random = RandomUtils.nextBytes(1000);
        final OutputStream out = local.getOutputStream(false);
        IOUtils.write(random, out);
        out.close();
        final TransferStatus status = new TransferStatus();
        status.setLength(random.length);
        status.setMime("text/plain");
        service.upload(test, local, new BandwidthThrottle(BandwidthThrottle.UNLIMITED),
                new DisabledStreamListener(), status, new DisabledLoginCallback());
        assertTrue(new S3FindFeature(session, new S3AccessControlListFeature(session)).find(test));
        final PathAttributes attr = new S3AttributesFinderFeature(session, new S3AccessControlListFeature(session)).find(test);
        assertEquals(status.getResponse().getChecksum(), attr.getChecksum());
        assertEquals(status.getResponse().getETag(), attr.getETag());
        assertEquals(random.length, attr.getSize());
        new S3DefaultDeleteFeature(session).delete(Collections.singletonList(test), new DisabledLoginCallback(), new Delete.DisabledCallback());
        local.delete();
    }