mschilli / net-google-drive-simple

Net::Google::Drive::Simple CPAN Module
Other
11 stars 22 forks source link

Introduce resumable uploads #61

Closed xsawyerx closed 2 years ago

xsawyerx commented 2 years ago

There are two main steps:

  1. Create a resumable URI so we can upload
  2. Upload to the resumable URI (Optional 3. Continue uploading if interrupted)

Creating the resumable URI

We introduce two methods for creating the initial URI, one using a file and one that does not require a file.

# Using a filename:
my $uri = $gd->create_resumable_upload_for( $file, $params );

# Without a filename:
my $uri = $gd->create_resumable_upload($params);

This will use the file to choose the default filename and mime type, but those can be provided to override. We also use the file to verify the file size limit, which we can't do if you don't provide a file.

Uploading the content

Once you create an upload URI, you can upload the content in one of the following ways:

  1. Upload all at once (still internally chunked)
my $upload_uri = $gd->create_resumable_upload_for($file, {...});
$gd->upload_file_content_single( $upload_uri, $file );

This will internally use chunks of 4K when reading the file while sending. This is going to be somewhat slower and with more disk I/O but should be safe for normal size files.

  1. Upload in parts
my $upload_uri = $gd->create_resumable_upload_for($file, {...});

# Default chunk size: 10M
$gd->upload_file_content_multiple( $upload_uri, $file );

# Specific chunk size: 20M
$gd->upload_file_content_multiple(
    $upload_uri,
    $file,
    1024 * 1024 * 20, # in bytes
);

When using this method, instead of chunks of 4K, we read in chunks of 10MB by default (or any other size you provide, as long as it divides by 256K).

The two major benefits of this technique is that it can use larger chunks when uploading (and you can control that), and that it can resume when it stops. The problem is that we don't yet handle that or allow you to handle that.

  1. Upload in parts using a callback iterator
my $upload_uri = $gd->create_resumable_upload_for($file, {...});

# Return an iterator callback
my $iter_cb = $gd->upload_file_content_iterator(
    $upload_uri,
    $file,
    $optional_chunk_size
);

while ( my $http_request = $iter_cb->() ) {
    ...
}

With the iterator, you can request the HTTP::Request object which would have been used. This lets you control the request itself so you could iterate over it with a problem. (However, you still need to make the initial synchronous request to generate the upload URI.)

Problems:

xsawyerx commented 2 years ago

I've added upload_file() which handles a resumable upload (that is, files till 5120 GB) without any special parameters, other than a file.