Mercurial > lbo > hg > async-google-apis
changeset 91:6d501f826123
New generated code with resumable uploads.
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Sat, 24 Oct 2020 21:46:34 +0200 |
parents | e031af86de5b |
children | eb7dcf74f9fd |
files | drive_example/Cargo.lock drive_example/Cargo.toml drive_example/src/drive_v3_types.rs drive_example/src/main.rs |
diffstat | 4 files changed, 94 insertions(+), 31 deletions(-) [+] |
line wrap: on
line diff
--- a/drive_example/Cargo.lock Sat Oct 24 21:46:19 2020 +0200 +++ b/drive_example/Cargo.lock Sat Oct 24 21:46:34 2020 +0200 @@ -33,6 +33,7 @@ dependencies = [ "anyhow", "chrono", + "futures", "hyper", "hyper-rustls", "log", @@ -69,9 +70,9 @@ [[package]] name = "base64" -version = "0.12.3" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" +checksum = "53d1ccbaf7d9ec9537465a97bf19edc1a4e158ecb49fc16178202238c569cc42" [[package]] name = "bitflags" @@ -151,7 +152,6 @@ "env_logger", "hyper", "hyper-rustls", - "rustls 0.17.0", "serde", "tokio", ] @@ -395,7 +395,7 @@ "futures-util", "hyper", "log", - "rustls 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls", "rustls-native-certs", "tokio", "tokio-rustls", @@ -746,17 +746,6 @@ [[package]] name = "rustls" version = "0.17.0" -dependencies = [ - "base64 0.11.0", - "log", - "ring", - "sct", - "webpki", -] - -[[package]] -name = "rustls" -version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0d4a31f5d68413404705d6982529b0e11a9aacd4839d1d6222ee3b8cb4015e1" dependencies = [ @@ -774,7 +763,7 @@ checksum = "a75ffeb84a6bd9d014713119542ce415db3a3e4748f0bfce1e1416cd224a23a5" dependencies = [ "openssl-probe", - "rustls 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls", "schannel", "security-framework", ] @@ -987,7 +976,7 @@ checksum = "15cb62a0d2770787abc96e99c1cd98fcf17f94959f3af63ca85bdfb203f051b4" dependencies = [ "futures-core", - "rustls 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls", "tokio", "webpki", ] @@ -1239,7 +1228,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "749192b9464694a95dbaf0586e845c835b315e38d491aa2766a8477aaadb48ec" dependencies = [ - "base64 0.12.3", + "base64 0.12.1", "chrono", "futures", "http", @@ -1247,7 +1236,7 @@ "hyper-rustls", "log", "percent-encoding", - "rustls 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls", "seahash", "serde", "serde_json",
--- a/drive_example/Cargo.toml Sat Oct 24 21:46:19 2020 +0200 +++ b/drive_example/Cargo.toml Sat Oct 24 21:46:34 2020 +0200 @@ -12,7 +12,6 @@ anyhow = "~1.0" serde = "~1.0" env_logger = "~0.8" -rustls = { path = "/home/lbo/rust/rustls/rustls", version = "0.17" } hyper-rustls = "~0.20" hyper = "~0.13" tokio = { version = "~0.2", features = ["full"] }
--- a/drive_example/src/drive_v3_types.rs Sat Oct 24 21:46:19 2020 +0200 +++ b/drive_example/src/drive_v3_types.rs Sat Oct 24 21:46:34 2020 +0200 @@ -3944,9 +3944,8 @@ } else { tok = self.authenticator.token(&self.scopes).await?; } - let mut url_params = format!("?uploadType=multipart&oauth_token={token}", token=tok.as_str()); - - url_params.push_str(&format!("{}", params)); + let mut url_params = format!("?uploadType=multipart&oauth_token={token}{params}", token=tok.as_str(), params=params); + if let Some(ref api_params) = ¶ms.drive_params { url_params.push_str(&format!("{}", api_params)); } @@ -3959,6 +3958,42 @@ } +/// Creates a new file. +/// +/// This method is a variant of `create()`, taking data for upload. +pub async fn create_resumable_upload<'client>( + &'client mut self, params: &FilesCreateParams, req: &File) -> Result<ResumableUpload<'client, File>> { + + let rel_path = "upload/drive/v3/files"; + let path = "https://www.googleapis.com/".to_string() + &rel_path; + let tok; + if self.scopes.is_empty() { + let scopes = &["https://www.googleapis.com/auth/drive.file".to_string(), + ]; + tok = self.authenticator.token(scopes).await?; + } else { + tok = self.authenticator.token(&self.scopes).await?; + } + let mut url_params = format!("?uploadType=resumable&oauth_token={token}{params}", token=tok.as_str(), params=params); + if let Some(ref api_params) = ¶ms.drive_params { + url_params.push_str(&format!("{}", api_params)); + } + + let full_uri = path + &url_params; + + let opt_request: Option<EmptyRequest> = None; + let opt_request = Some(req); + let (_resp, headers): (EmptyResponse, hyper::HeaderMap) = do_request_with_headers(&self.client, &full_uri, &[], "POST", opt_request).await?; + if let Some(dest) = headers.get(hyper::header::LOCATION) { + use std::convert::TryFrom; + Ok(ResumableUpload::new(hyper::Uri::try_from(dest.to_str()?)?, &self.client, 256*1024)) + } else { + Err(Error::from(ApiError::RedirectError(format!("Resumable upload response didn't contain Location: {:?}", headers))) + .context(format!("{:?}", headers)))? + } + } + + /// Permanently deletes a file owned by the user without moving it to the trash. If the file belongs to a shared drive the user must be an organizer on the parent. If the target is a folder, all descendants owned by the user are also deleted. pub async fn delete( &mut self, params: &FilesDeleteParams) -> Result<()> { @@ -4163,9 +4198,8 @@ } else { tok = self.authenticator.token(&self.scopes).await?; } - let mut url_params = format!("?uploadType=multipart&oauth_token={token}", token=tok.as_str()); - - url_params.push_str(&format!("{}", params)); + let mut url_params = format!("?uploadType=multipart&oauth_token={token}{params}", token=tok.as_str(), params=params); + if let Some(ref api_params) = ¶ms.drive_params { url_params.push_str(&format!("{}", api_params)); } @@ -4178,6 +4212,42 @@ } +/// Updates a file's metadata and/or content. This method supports patch semantics. +/// +/// This method is a variant of `update()`, taking data for upload. +pub async fn update_resumable_upload<'client>( + &'client mut self, params: &FilesUpdateParams, req: &File) -> Result<ResumableUpload<'client, File>> { + + let rel_path = "upload/drive/v3/files/{fileId}"; + let path = "https://www.googleapis.com/".to_string() + &rel_path; + let tok; + if self.scopes.is_empty() { + let scopes = &["https://www.googleapis.com/auth/drive.scripts".to_string(), + ]; + tok = self.authenticator.token(scopes).await?; + } else { + tok = self.authenticator.token(&self.scopes).await?; + } + let mut url_params = format!("?uploadType=resumable&oauth_token={token}{params}", token=tok.as_str(), params=params); + if let Some(ref api_params) = ¶ms.drive_params { + url_params.push_str(&format!("{}", api_params)); + } + + let full_uri = path + &url_params; + + let opt_request: Option<EmptyRequest> = None; + let opt_request = Some(req); + let (_resp, headers): (EmptyResponse, hyper::HeaderMap) = do_request_with_headers(&self.client, &full_uri, &[], "PATCH", opt_request).await?; + if let Some(dest) = headers.get(hyper::header::LOCATION) { + use std::convert::TryFrom; + Ok(ResumableUpload::new(hyper::Uri::try_from(dest.to_str()?)?, &self.client, 256*1024)) + } else { + Err(Error::from(ApiError::RedirectError(format!("Resumable upload response didn't contain Location: {:?}", headers))) + .context(format!("{:?}", headers)))? + } + } + + /// Subscribes to changes to a file pub async fn watch( &mut self, params: &FilesWatchParams, req: &Channel) -> Result<Channel> {
--- a/drive_example/src/main.rs Sat Oct 24 21:46:19 2020 +0200 +++ b/drive_example/src/main.rs Sat Oct 24 21:46:34 2020 +0200 @@ -26,27 +26,32 @@ /// Upload a local file `f` to your drive. async fn upload_file(mut cl: drive::FilesService, f: &Path) -> anyhow::Result<()> { - cl.set_scopes(&[drive::DriveScopes::DriveFile]); let fname = f.file_name().unwrap().to_str().unwrap(); let mut general_params = drive::DriveParams::default(); general_params.fields = Some("*".to_string()); - let data = hyper::body::Bytes::from(fs::read(&f)?); let mut params = drive::FilesCreateParams::default(); params.drive_params = Some(general_params.clone()); params.include_permissions_for_view = Some("published".to_string()); - println!("{:?}", params); let mut file = drive::File::default(); file.name = Some(fname.to_string()); // Upload data using the upload version of create(). We obtain a `File` object. // - let resp = cl.create_upload(¶ms, &file, data).await?; + let resumable = cl.create_resumable_upload(¶ms, &file).await?; + + let tokiofile = tokio::fs::OpenOptions::new().read(true).open(f).await?; + let resp = resumable.upload_file(tokiofile).await?; // If you used this method, no file content would be uploaded: // let resp = cl.create(¶ms, &file).await?; - println!("{:?}", resp); + println!( + "Uploaded file: {} (id = {}) with metadata: \n {:?}", + resp.name.as_ref().unwrap(), + resp.id.as_ref().unwrap(), + resp + ); let file_id = resp.id.unwrap();