dynamo_async_openai/
uploads.rs

1// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2// SPDX-License-Identifier: Apache-2.0
3//
4// Based on https://github.com/64bit/async-openai/ by Himanshu Neema
5// Original Copyright (c) 2022 Himanshu Neema
6// Licensed under MIT License (see ATTRIBUTIONS-Rust.md)
7//
8// Modifications Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
9// Licensed under Apache 2.0
10
11use crate::{
12    Client,
13    config::Config,
14    error::OpenAIError,
15    types::{AddUploadPartRequest, CompleteUploadRequest, CreateUploadRequest, Upload, UploadPart},
16};
17
18/// Allows you to upload large files in multiple parts.
19pub struct Uploads<'c, C: Config> {
20    client: &'c Client<C>,
21}
22
23impl<'c, C: Config> Uploads<'c, C> {
24    pub fn new(client: &'c Client<C>) -> Self {
25        Self { client }
26    }
27
28    /// Creates an intermediate [Upload](https://platform.openai.com/docs/api-reference/uploads/object) object that
29    /// you can add [Parts](https://platform.openai.com/docs/api-reference/uploads/part-object) to. Currently,
30    /// an Upload can accept at most 8 GB in total and expires after an hour after you create it.
31    ///
32    /// Once you complete the Upload, we will create a [File](https://platform.openai.com/docs/api-reference/files/object)
33    /// object that contains all the parts you uploaded. This File is usable in the rest of our platform as a regular File object.
34    ///
35    /// For certain `purpose`s, the correct `mime_type` must be specified. Please refer to documentation for the
36    /// supported MIME types for your use case:
37    /// - [Assistants](https://platform.openai.com/docs/assistants/tools/file-search/supported-files)
38    ///
39    /// For guidance on the proper filename extensions for each purpose, please follow the documentation on
40    /// [creating a File](https://platform.openai.com/docs/api-reference/files/create).
41    #[crate::byot(T0 = serde::Serialize, R = serde::de::DeserializeOwned)]
42    pub async fn create(&self, request: CreateUploadRequest) -> Result<Upload, OpenAIError> {
43        self.client.post("/uploads", request).await
44    }
45
46    /// Adds a [Part](https://platform.openai.com/docs/api-reference/uploads/part-object) to an
47    /// [Upload](https://platform.openai.com/docs/api-reference/uploads/object) object.
48    /// A Part represents a chunk of bytes from the file you are trying to upload.
49    ///
50    /// Each Part can be at most 64 MB, and you can add Parts until you hit the Upload maximum of 8 GB.
51    ///
52    /// It is possible to add multiple Parts in parallel. You can decide the intended order of the Parts
53    /// when you [complete the Upload](https://platform.openai.com/docs/api-reference/uploads/complete).
54    #[crate::byot(
55        T0 = std::fmt::Display,
56        T1 = Clone,
57        R = serde::de::DeserializeOwned,
58        where_clause =  "reqwest::multipart::Form: crate::traits::AsyncTryFrom<T1, Error = OpenAIError>")]
59    pub async fn add_part(
60        &self,
61        upload_id: &str,
62        request: AddUploadPartRequest,
63    ) -> Result<UploadPart, OpenAIError> {
64        self.client
65            .post_form(&format!("/uploads/{upload_id}/parts"), request)
66            .await
67    }
68
69    /// Completes the [Upload](https://platform.openai.com/docs/api-reference/uploads/object).
70    ///
71    /// Within the returned Upload object, there is a nested [File](https://platform.openai.com/docs/api-reference/files/object)
72    /// object that is ready to use in the rest of the platform.
73    ///
74    /// You can specify the order of the Parts by passing in an ordered list of the Part IDs.
75    ///
76    /// The number of bytes uploaded upon completion must match the number of bytes initially specified
77    /// when creating the Upload object. No Parts may be added after an Upload is completed.
78
79    #[crate::byot(T0 = std::fmt::Display, T1 = serde::Serialize, R = serde::de::DeserializeOwned)]
80    pub async fn complete(
81        &self,
82        upload_id: &str,
83        request: CompleteUploadRequest,
84    ) -> Result<Upload, OpenAIError> {
85        self.client
86            .post(&format!("/uploads/{upload_id}/complete"), request)
87            .await
88    }
89
90    /// Cancels the Upload. No Parts may be added after an Upload is cancelled.
91    #[crate::byot(T0 = std::fmt::Display, R = serde::de::DeserializeOwned)]
92    pub async fn cancel(&self, upload_id: &str) -> Result<Upload, OpenAIError> {
93        self.client
94            .post(
95                &format!("/uploads/{upload_id}/cancel"),
96                serde_json::json!({}),
97            )
98            .await
99    }
100}