Skip to main content

canvas_lms_api/resources/
file.rs

1use crate::{error::Result, http::Requester, params::flatten_params};
2use chrono::{DateTime, Utc};
3use serde::{Deserialize, Serialize};
4use std::sync::Arc;
5
6/// Parameters for updating a Canvas file.
7#[derive(Debug, Default, Clone, Serialize)]
8pub struct UpdateFileParams {
9    #[serde(skip_serializing_if = "Option::is_none")]
10    pub name: Option<String>,
11    #[serde(skip_serializing_if = "Option::is_none")]
12    pub parent_folder_id: Option<u64>,
13    #[serde(skip_serializing_if = "Option::is_none")]
14    pub on_duplicate: Option<String>,
15    #[serde(skip_serializing_if = "Option::is_none")]
16    pub locked: Option<bool>,
17    #[serde(skip_serializing_if = "Option::is_none")]
18    pub hidden: Option<bool>,
19}
20
21/// A file stored in Canvas.
22#[derive(Debug, Clone, Deserialize, Serialize, canvas_lms_api_derive::CanvasResource)]
23pub struct File {
24    pub id: u64,
25    pub uuid: Option<String>,
26    pub folder_id: Option<u64>,
27    pub display_name: Option<String>,
28    pub filename: Option<String>,
29    pub content_type: Option<String>,
30    pub url: Option<String>,
31    pub size: Option<u64>,
32    pub created_at: Option<DateTime<Utc>>,
33    pub updated_at: Option<DateTime<Utc>>,
34    pub unlock_at: Option<DateTime<Utc>>,
35    pub locked: Option<bool>,
36    pub hidden: Option<bool>,
37    pub lock_at: Option<DateTime<Utc>>,
38    pub hidden_for_user: Option<bool>,
39    pub thumbnail_url: Option<String>,
40    pub modified_at: Option<DateTime<Utc>>,
41    pub mime_class: Option<String>,
42    pub media_entry_id: Option<String>,
43    pub locked_for_user: Option<bool>,
44
45    #[serde(skip)]
46    pub(crate) requester: Option<Arc<Requester>>,
47}
48
49impl File {
50    /// Update metadata (name, folder, lock state) of this file.
51    ///
52    /// # Canvas API
53    /// `PUT /api/v1/files/:id`
54    pub async fn update(&self, params: UpdateFileParams) -> Result<File> {
55        let form = flatten_params(&serde_json::to_value(&params).unwrap());
56        let mut f: File = self.req().put(&format!("files/{}", self.id), &form).await?;
57        f.requester = self.requester.clone();
58        Ok(f)
59    }
60
61    /// Delete this file.
62    ///
63    /// # Canvas API
64    /// `DELETE /api/v1/files/:id`
65    pub async fn delete(&self) -> Result<File> {
66        let mut f: File = self
67            .req()
68            .delete(&format!("files/{}", self.id), &[])
69            .await?;
70        f.requester = self.requester.clone();
71        Ok(f)
72    }
73
74    /// Download the raw bytes of this file's content.
75    ///
76    /// Uses the file's `url` field (an absolute Canvas file URL).
77    pub async fn get_contents(&self) -> Result<Vec<u8>> {
78        let url = self.url.as_deref().unwrap_or("");
79        self.req().get_url_bytes(url).await
80    }
81
82    /// Download this file to a local path.
83    pub async fn download(&self, path: &std::path::Path) -> Result<()> {
84        let bytes = self.get_contents().await?;
85        std::fs::write(path, bytes)?;
86        Ok(())
87    }
88}