@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 {
                try {
                    // Initiate a resumable upload
                    final HttpEntityEnclosingRequestBase request;
                    if(status.isExists()) {
                        final String fileid = DriveWriteFeature.this.fileid.getFileId(file);
                        request = new HttpPatch(String.format("%supload/drive/v3/files/%s?supportsAllDrives=true&fields=%s",
                                session.getClient().getRootUrl(), fileid, DriveAttributesFinderFeature.DEFAULT_FIELDS));
                        if(StringUtils.isNotBlank(status.getMime())) {
                            request.setHeader(HttpHeaders.CONTENT_TYPE, status.getMime());
                        }
                        // Upload the file
                        request.setEntity(entity);
                    }
                    else {
                        request = new HttpPost(String.format("%supload/drive/v3/files?uploadType=resumable&supportsAllDrives=%s&fields=%s",
                                session.getClient().getRootUrl(), new HostPreferences(session.getHost()).getBoolean("googledrive.teamdrive.enable"),
                                DriveAttributesFinderFeature.DEFAULT_FIELDS));
                        final StringBuilder metadata = new StringBuilder("{");
                        metadata.append(String.format("\"name\":\"%s\"", file.getName()));
                        if(null != status.getModified()) {
                            metadata.append(String.format(",\"modifiedTime\":\"%s\"",
                                    new ISO8601DateFormatter().format(status.getModified(), TimeZone.getTimeZone("UTC"))));
                        }
                        if(null != status.getCreated()) {
                            metadata.append(String.format(",\"createdTime\":\"%s\"",
                                    new ISO8601DateFormatter().format(status.getCreated(), TimeZone.getTimeZone("UTC"))));
                        }
                        if(StringUtils.isNotBlank(status.getMime())) {
                            metadata.append(String.format(",\"mimeType\":\"%s\"", status.getMime()));
                        }
                        metadata.append(String.format(",\"parents\":[\"%s\"]", fileid.getFileId(file.getParent())));
                        metadata.append("}");
                        request.setEntity(new StringEntity(metadata.toString(),
                                ContentType.create("application/json", StandardCharsets.UTF_8.name())));
                        if(StringUtils.isNotBlank(status.getMime())) {
                            // Set to the media MIME type of the upload data to be transferred in subsequent requests.
                            request.addHeader("X-Upload-Content-Type", status.getMime());
                        }
                    }
                    request.addHeader(HTTP.CONTENT_TYPE, MEDIA_TYPE);
                    final HttpClient client = session.getHttpClient();
                    final HttpResponse postResponse = client.execute(request);
                    try {
                        switch(postResponse.getStatusLine().getStatusCode()) {
                            case HttpStatus.SC_OK:
                                if(status.isExists()) {
                                    final File f = session.getClient().getObjectParser().parseAndClose(
                                            new InputStreamReader(postResponse.getEntity().getContent(), StandardCharsets.UTF_8), File.class);
                                    if(null != status.getModified()) {
                                        new DriveTimestampFeature(session, fileid).setTimestamp(file, status);
                                        f.setModifiedTime(new DateTime(status.getModified()));
                                    }
                                    return f;
                                }
                                break;
                            default:
                                throw new DefaultHttpResponseExceptionMappingService().map("Upload {0} failed",
                                        new HttpResponseException(postResponse.getStatusLine().getStatusCode(), postResponse.getStatusLine().getReasonPhrase()), file);
                        }
                    }
                    finally {
                        EntityUtils.consume(postResponse.getEntity());
                    }
                    if(!status.isExists()) {
                        if(postResponse.containsHeader(HttpHeaders.LOCATION)) {
                            final String putTarget = postResponse.getFirstHeader(HttpHeaders.LOCATION).getValue();
                            // Upload the file
                            final HttpPut put = new HttpPut(putTarget);
                            put.setEntity(entity);
                            final HttpResponse putResponse = client.execute(put);
                            try {
                                switch(putResponse.getStatusLine().getStatusCode()) {
                                    case HttpStatus.SC_OK:
                                    case HttpStatus.SC_CREATED:
                                        final File response = session.getClient().getObjectParser().parseAndClose(
                                                new InputStreamReader(putResponse.getEntity().getContent(), StandardCharsets.UTF_8), File.class);
                                        fileid.cache(file, response.getId());
                                        return response;
                                    default:
                                        throw new DefaultHttpResponseExceptionMappingService().map("Upload {0} failed",
                                                new HttpResponseException(putResponse.getStatusLine().getStatusCode(), putResponse.getStatusLine().getReasonPhrase()), file);
                                }
                            }
                            finally {
                                EntityUtils.consume(putResponse.getEntity());
                            }
                        }
                        else {
                            throw new DefaultHttpResponseExceptionMappingService().map("Upload {0} failed",
                                    new HttpResponseException(postResponse.getStatusLine().getStatusCode(), postResponse.getStatusLine().getReasonPhrase()), file);
                        }
                    }
                    return null;
                }
                catch(IOException e) {
                    throw new DriveExceptionMappingService(fileid).map("Upload {0} failed", e, file);
                }
            }

            @Override
            public long getContentLength() {
                return status.getLength();
            }
        };
        return this.write(file, status, command);
    }
@Test
    public void testWrite() throws Exception {
        final DriveFileIdProvider idProvider = new DriveFileIdProvider(session);
        final Path folder = new DriveDirectoryFeature(session, idProvider).mkdir(
                new Path(DriveHomeFinderService.MYDRIVE_FOLDER, UUID.randomUUID().toString(), EnumSet.of(Path.Type.directory)), new TransferStatus());
        final Path test = new Path(folder, new AlphanumericRandomStringService().random(), EnumSet.of(Path.Type.file));
        String fileid;
        {
            final TransferStatus status = new TransferStatus();
            status.setMime("x-application/cyberduck");
            status.setModified(1620113107725L);
            status.setCreated(1695160857860L);
            final byte[] content = RandomUtils.nextBytes(2048);
            status.setLength(content.length);
            final HttpResponseOutputStream<File> out = new DriveWriteFeature(session, idProvider).write(test, status, new DisabledConnectionCallback());
            new StreamCopier(new TransferStatus(), new TransferStatus()).transfer(new ByteArrayInputStream(content), out);
            fileid = out.getStatus().getId();
            assertNotNull(fileid);
            assertTrue(new DefaultFindFeature(session).find(test));
            assertEquals(status.getModified(), new DriveAttributesFinderFeature(session, idProvider).toAttributes(out.getStatus()).getModificationDate(), 0L);
            final PathAttributes attributes = new DriveAttributesFinderFeature(session, idProvider).find(test);
            assertEquals(new DriveAttributesFinderFeature(session, idProvider).toAttributes(out.getStatus()), attributes);
            assertEquals(fileid, attributes.getFileId());
            assertEquals(1620113107725L, attributes.getModificationDate());
            assertEquals(1695160857860L, attributes.getCreationDate());
            assertEquals(content.length, attributes.getSize());
            final byte[] buffer = new byte[content.length];
            final InputStream in = new DriveReadFeature(session, idProvider).read(test, new TransferStatus(), new DisabledConnectionCallback());
            IOUtils.readFully(in, buffer);
            in.close();
            assertArrayEquals(content, buffer);
            assertEquals("x-application/cyberduck", session.getClient().files().get(test.attributes().getFileId()).execute().getMimeType());
        }
        {
            // overwrite
            final TransferStatus status = new TransferStatus();
            status.setMime("x-application/cyberduck");
            status.setModified(System.currentTimeMillis());
            status.setExists(true);
            final byte[] content = RandomUtils.nextBytes(1024);
            status.setLength(content.length);
            final HttpResponseOutputStream<File> out = new DriveWriteFeature(session, idProvider).write(test, status, new DisabledConnectionCallback());
            new StreamCopier(new TransferStatus(), new TransferStatus()).transfer(new ByteArrayInputStream(content), out);
            assertEquals(fileid, out.getStatus().getId());
            final PathAttributes attributes = new DriveListService(session, idProvider).list(test.getParent(), new DisabledListProgressListener()).get(test).attributes();
            assertEquals(content.length, attributes.getSize());
            assertEquals("x-application/cyberduck", session.getClient().files().get(test.attributes().getFileId()).execute().getMimeType());
            assertEquals(status.getModified().longValue(), new DriveAttributesFinderFeature(session, idProvider).toAttributes(out.getStatus()).getModificationDate());
            assertEquals(new DriveAttributesFinderFeature(session, idProvider).toAttributes(out.getStatus()), attributes);
        }
        new DriveDeleteFeature(session, idProvider).delete(Arrays.asList(test, folder), new DisabledLoginCallback(), new Delete.DisabledCallback());
    }