{"id":35313,"date":"2024-08-23T07:00:00","date_gmt":"2024-08-23T14:00:00","guid":{"rendered":"https:\/\/cloudinary.com\/blog\/?p=35313"},"modified":"2025-03-30T02:26:59","modified_gmt":"2025-03-30T09:26:59","slug":"how-to-upload-a-video-in-a-rust-backend","status":"publish","type":"post","link":"https:\/\/cloudinary.com\/blog\/how-to-upload-a-video-in-a-rust-backend","title":{"rendered":"How to Upload a Video in a Rust Backend"},"content":{"rendered":"\n<p>Uploading videos is a common requirement for modern web applications, and handling this functionality efficiently on the server side is important. <a target=\"_blank\" href=\"https:\/\/www.rust-lang.org\/\" rel=\"noreferrer noopener\">Rust<\/a>&#8216;s performance and safety features are an excellent choice for backend development, while <a target=\"_blank\" href=\"https:\/\/cloudinary.com\/\" rel=\"noreferrer noopener\">Cloudinary<\/a> offers powerful cloud-based media management solutions.<\/p>\n\n\n\n<p>This blog post will guide you through uploading a video in a Rust backend with Cloudinary. You\u2019ll learn how to set up your Rust environment, configure Cloudinary, and implement video upload functionality in a few steps.<\/p>\n\n\n\n<p><a href=\"https:\/\/cloudinary.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Cloudinary<\/a> provides a secure and comprehensive API for quickly uploading media files from server-side code, directly from the browser or a mobile application.<\/p>\n\n\n\n<p>The <a href=\"https:\/\/github.com\/Olanetsoft\/cloudinary-rust\">Github repository is here<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<p>To get the most out of this article, you should have:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/doc.rust-lang.org\/cargo\/getting-started\/installation.html\" target=\"_blank\" rel=\"noreferrer noopener\">Rust and Cargo<\/a> installed.<\/li>\n\n\n\n<li>Basic understanding of Rust.<\/li>\n\n\n\n<li><a href=\"https:\/\/www.postman.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Postman<\/a> or any API testing application installed.<\/li>\n\n\n\n<li>A free <a href=\"https:\/\/cloudinary.com\/users\/register\/free?utm_source=hackmamba&amp;utm_campaign=hackmamba-hackathon&amp;utm_medium=hackmamba-blog\" target=\"_blank\" rel=\"noreferrer noopener\">Cloudinary account<\/a>.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Project Setup and Installation<\/h2>\n\n\n\n<p>To upload a video to Cloudinary using a Rust backend, create a new Rust project and install the required dependencies. Use the following command to initialize a new project and navigate to the project:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">cargo <span class=\"hljs-keyword\">new<\/span> cloudinary-rust &amp;&amp; cd cloudinary-rust<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Update the <code>[dependencies]<\/code> section of the <code>cargo.toml<\/code> file in the project&#8217;s root directory to include all the dependencies you&#8217;ll use in this tutorial. The dependencies include:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>actix-web<\/code>. A Rust-based framework for building web applications.<\/li>\n\n\n\n<li><code>actix-multipart<\/code>. A library used alongside <code>actix-web<\/code> to handle form data.<\/li>\n\n\n\n<li><code>dotenv<\/code>. A library for loading environment variables.<\/li>\n\n\n\n<li><code>reqwest = { version = \"0.11\", features = [\"multipart\"] }<\/code>. A library for making HTTP requests with support for multipart form data.<\/li>\n\n\n\n<li><code>serde = { version = \"1.0.195\", features = [\"derive\"] }<\/code>. A framework for serializing and deserializing Rust data structures.<\/li>\n\n\n\n<li><code>serde_json<\/code>. A library for parsing <code>JSON<\/code> data.<\/li>\n\n\n\n<li><code>tokio = { version = \"1\", features = [\"full\"] }<\/code>. A runtime for handling asynchronous programming in Rust.<\/li>\n\n\n\n<li><code>futures-util<\/code>. A utility and combinator for handling future and asynchronous programming in Rust.<\/li>\n\n\n\n<li><code>mime<\/code>. A library for handling <code>MIME<\/code> types in Rust.<\/li>\n\n\n\n<li><code>sha1<\/code>. A library for hashing in Rust.<\/li>\n\n\n\n<li><code>hex<\/code>. A library for encoding and decoding hexadecimal data.<\/li>\n\n\n\n<li><code>chrono<\/code>. A \u00a0Rust library for handling date and time.<\/li>\n\n\n\n<li><code>tempfile<\/code>. A library for creating temporary files and directories.\u00a0<\/li>\n<\/ul>\n\n\n\n<p>Next, update the <code>cargo.toml<\/code> file with the following dependencies:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-wrap-lines\">&#91;package]\nname = <span class=\"hljs-string\">\"cloudinary-rust\"<\/span>\nversion = <span class=\"hljs-string\">\"0.1.0\"<\/span>\nedition = <span class=\"hljs-string\">\"2021\"<\/span>\n\n<span class=\"hljs-comment\"># See more keys and their definitions at https:\/\/doc.rust-lang.org\/cargo\/reference\/manifest.html<\/span>\n\n&#91;dependencies]\nactix-web = <span class=\"hljs-string\">\"4.5\"<\/span>\nactix-multipart = <span class=\"hljs-string\">\"0.6\"<\/span>\ndotenv = <span class=\"hljs-string\">\"0.15.0\"<\/span>\nreqwest = { version = <span class=\"hljs-string\">\"0.11\"<\/span>, features = &#91;<span class=\"hljs-string\">\"multipart\"<\/span>] }\nserde = { version = <span class=\"hljs-string\">\"1.0.195\"<\/span>, features = &#91;<span class=\"hljs-string\">\"derive\"<\/span>] }\nserde_json = <span class=\"hljs-string\">\"1.0.111\"<\/span>\ntokio = { version = <span class=\"hljs-string\">\"1\"<\/span>, features = &#91;<span class=\"hljs-string\">\"full\"<\/span>] }\nfutures-util = <span class=\"hljs-string\">\"0.3\"<\/span>\nmime = <span class=\"hljs-string\">\"0.3\"<\/span>\nsha1 = <span class=\"hljs-string\">\"0.10\"<\/span>\nhex = <span class=\"hljs-string\">\"0.4\"<\/span>\nchrono = <span class=\"hljs-string\">\"0.4\"<\/span>\ntempfile = <span class=\"hljs-string\">\"3.3\"<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Next, run the command below to install all the dependencies listed in the <code>cargo.toml<\/code> file:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs shcb-wrap-lines\">cargo run<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Build the Video Upload API<\/h2>\n\n\n\n<p>Cloudinary allows developers to upload, store, manage, optimize, and deliver images and videos. When uploading media assets, Cloudinary provides two major ways to upload:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Unsigned uploads<\/strong>. Allow uploads to Cloudinary without requiring the generation of authentication signatures.<\/li>\n\n\n\n<li><strong>Signed uploads<\/strong>. Require a secure <a href=\"https:\/\/cloudinary.com\/documentation\/authentication_signatures\" target=\"_blank\" rel=\"noreferrer noopener\">signature<\/a> to authorize each upload request to Cloudinary.<\/li>\n<\/ul>\n\n\n\n<p>While both upload methods let you upload your media assets to Cloudinary, they differ in use cases and implementation. For this tutorial, we\u2019ll use <a target=\"_blank\" href=\"https:\/\/cloudinary.com\/documentation\/authentication_signatures\" rel=\"noreferrer noopener\">signed uploads<\/a>.<\/p>\n\n\n\n<p>Next, retrieve your Cloudinary <strong>Cloud name<\/strong>, <strong>API key<\/strong>, and <strong>API secret<\/strong> from the Cloudinary dashboard.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Get Environment Variables From Cloudinary\u00a0<\/strong><\/h3>\n\n\n\n<p>Log in to your Cloudinary dashboard to get product environment credentials such as the <strong>Cloud name<\/strong>, <strong>API key<\/strong>, and <strong>API secret<\/strong>. \u00a0<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img width=\"1024\" height=\"445\" data-public-id=\"Web_Assets\/blog\/blog-How-to-Upload-a-Video-in-a-Rust-Backend-1\/blog-How-to-Upload-a-Video-in-a-Rust-Backend-1.png\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/w_1024,h_445,c_scale\/f_auto,q_auto\/v1724098401\/Web_Assets\/blog\/blog-How-to-Upload-a-Video-in-a-Rust-Backend-1\/blog-How-to-Upload-a-Video-in-a-Rust-Backend-1.png?_i=AA\" alt=\"\" class=\"wp-post-35313 wp-image-35314\" data-format=\"png\" data-transformations=\"f_auto,q_auto\" data-version=\"1724098401\" data-seo=\"1\" srcset=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1724098401\/Web_Assets\/blog\/blog-How-to-Upload-a-Video-in-a-Rust-Backend-1\/blog-How-to-Upload-a-Video-in-a-Rust-Backend-1.png?_i=AA 1600w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1724098401\/Web_Assets\/blog\/blog-How-to-Upload-a-Video-in-a-Rust-Backend-1\/blog-How-to-Upload-a-Video-in-a-Rust-Backend-1.png?_i=AA 300w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1724098401\/Web_Assets\/blog\/blog-How-to-Upload-a-Video-in-a-Rust-Backend-1\/blog-How-to-Upload-a-Video-in-a-Rust-Backend-1.png?_i=AA 768w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1724098401\/Web_Assets\/blog\/blog-How-to-Upload-a-Video-in-a-Rust-Backend-1\/blog-How-to-Upload-a-Video-in-a-Rust-Backend-1.png?_i=AA 1024w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1724098401\/Web_Assets\/blog\/blog-How-to-Upload-a-Video-in-a-Rust-Backend-1\/blog-How-to-Upload-a-Video-in-a-Rust-Backend-1.png?_i=AA 1536w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Then, create a <code>.env<\/code> file in the root folder of the project using the following command:<\/p>\n\n\n\n<p><strong>For macOS and Linux:<\/strong><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\"><span class=\"hljs-selector-tag\">touch<\/span> <span class=\"hljs-selector-class\">.env<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><strong>For Windows(Command Prompt):<\/strong><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\"><span class=\"hljs-selector-tag\">type<\/span> <span class=\"hljs-selector-tag\">NUL<\/span> &gt; <span class=\"hljs-selector-class\">.env<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><strong>For Windows(PowerShell):<\/strong><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\"><span class=\"hljs-selector-tag\">New-Item<\/span> <span class=\"hljs-selector-tag\">-Path<\/span> <span class=\"hljs-selector-class\">.env<\/span> <span class=\"hljs-selector-tag\">-ItemType<\/span> <span class=\"hljs-selector-tag\">File<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Add your product credentials to the environment file:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">\nCLOUDINARY_CLOUD_NAME=<span class=\"hljs-string\">\"*********************\"<\/span>\nCLOUDINARY_API_KEY=<span class=\"hljs-string\">\"*********************\"<\/span>\nCLOUDINARY_API_SECRET=<span class=\"hljs-string\">\"*********************\"<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Replace <code>*********************<\/code> with your credentials.<\/p>\n\n\n\n<p>Replace ********************* with your credentials.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Create the API Models&nbsp;<\/strong><\/h3>\n\n\n\n<p>You must create an API model for the responses to help define the data structures representing and handling the data exchanged between the backend API and Cloudinary.&nbsp;<\/p>\n\n\n\n<p>Create a file named <code>models.rs<\/code> in the <code>src<\/code> folder and create <code>CloudinaryResponse<\/code>, <code>APIResponse<\/code>, and <code>APIErrorResponse<\/code> structs to describe the response body from Cloudinary and API responses.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-wrap-lines\">\n<span class=\"hljs-comment\">\/\/ src\/models.rs<\/span>\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">serde<\/span>::{<span class=\"hljs-title\">Deserialize<\/span>, <span class=\"hljs-title\">Serialize<\/span>};\n\n<span class=\"hljs-comment\">#&#91;derive(Serialize, Deserialize, Debug)]<\/span>\npub struct CloudinaryResponse {\n    pub public_id: String,\n    pub secure_url: String,\n}\n\n<span class=\"hljs-comment\">#&#91;derive(Serialize)]<\/span>\npub struct APIResponse&lt;T&gt; {\n    pub status: u16,\n    pub message: String,\n    pub data: Option&lt;T&gt;,\n}\n\n<span class=\"hljs-comment\">#&#91;derive(Serialize)]<\/span>\npub struct APIErrorResponse {\n    pub status: u16,\n    pub message: String,\n    pub data: Option&lt;String&gt;,\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><strong>Create the API Service<\/strong><\/p>\n\n\n\n<p>A best practice when creating APIs is to separate the application logic from the API handlers to make your code maintainable, testable, scalable, and reusable.&nbsp;<\/p>\n\n\n\n<p>In this API service, you\u2019ll:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Import the required dependencies.<\/li>\n\n\n\n<li>Create a <code>MAX_SIZE<\/code> constant and <code>ParamValue enum<\/code> to define the maximum size of an uploadable video and parameter types.<\/li>\n\n\n\n<li>Create a <code>VideoService<\/code> struct.<\/li>\n\n\n\n<li>Create an implementation block that includes<code> env_loader<\/code> and <code>generate_signature<\/code> methods. These methods load environment variables and generate a signature to authorize each upload request. The signature is generated by concatenating the parameters and appending the API secrets.<\/li>\n<\/ul>\n\n\n\n<p>Create a <code>video_service.rs<\/code> file in the <code>src<\/code> directory and add the following code for the API service below:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-wrap-lines\">\n<span class=\"hljs-comment\">\/\/ src\/video_service.rs<\/span>\n\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">crate<\/span>::<span class=\"hljs-title\">models<\/span>::<span class=\"hljs-title\">CloudinaryResponse<\/span>;\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">actix_multipart<\/span>::<span class=\"hljs-title\">Multipart<\/span>;\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">actix_web<\/span>::<span class=\"hljs-title\">Error<\/span>;\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">dotenv<\/span>::<span class=\"hljs-title\">dotenv<\/span>;\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">futures_util<\/span>::<span class=\"hljs-title\">StreamExt<\/span>;\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">reqwest<\/span>::{\n    <span class=\"hljs-title\">multipart<\/span>::{<span class=\"hljs-title\">self<\/span>, <span class=\"hljs-title\">Part<\/span>},\n    <span class=\"hljs-title\">Client<\/span>,\n};\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">sha1<\/span>::{<span class=\"hljs-title\">Digest<\/span>, <span class=\"hljs-title\">Sha1<\/span>};\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">std<\/span>::{<span class=\"hljs-title\">collections<\/span>::<span class=\"hljs-title\">HashMap<\/span>, <span class=\"hljs-title\">env<\/span>, <span class=\"hljs-title\">io<\/span>::<span class=\"hljs-title\">Write<\/span>};\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">tempfile<\/span>::<span class=\"hljs-title\">NamedTempFile<\/span>;\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">tokio<\/span>::<span class=\"hljs-title\">io<\/span>::<span class=\"hljs-title\">AsyncReadExt<\/span>;\n\n<span class=\"hljs-keyword\">const<\/span> MAX_SIZE: usize = <span class=\"hljs-number\">10<\/span> * <span class=\"hljs-number\">1024<\/span> * <span class=\"hljs-number\">1024<\/span>; <span class=\"hljs-comment\">\/\/ 10MB<\/span>\n\nenum ParamValue {\n    Str(String),\n    Int(i64),\n}\n\npub struct VideoService;\n\nimpl VideoService {\n    fn env_loader(key: &amp;str) -&gt; String {\n        dotenv().ok();\n        match env::var(key) {\n            Ok(v) =&gt; v.to_string(),\n            Err(_) =&gt; format!(<span class=\"hljs-string\">\"Error loading env variable\"<\/span>),\n        }\n    }\n\n    fn generate_signature(params: HashMap&lt;&amp;str, ParamValue&gt;, api_secret: &amp;str) -&gt; String {\n        <span class=\"hljs-comment\">\/\/ Step 1: Sort the parameters by keys and concatenate them<\/span>\n        let mut sorted_keys: Vec&lt;&amp;&amp;str&gt; = params.keys().collect();\n        sorted_keys.sort();\n        let mut sorted_params = String::new();\n        <span class=\"hljs-keyword\">for<\/span> key in sorted_keys {\n            <span class=\"hljs-keyword\">if<\/span> !sorted_params.is_empty() {\n                sorted_params.push(<span class=\"hljs-string\">'&amp;'<\/span>);\n            }\n            let value = match &amp;params&#91;key] {\n                ParamValue::Str(s) =&gt; s.<span class=\"hljs-keyword\">clone<\/span>(),\n                ParamValue::Int(i) =&gt; i.to_string(),\n            };\n            sorted_params.push_str(&amp;format!(<span class=\"hljs-string\">\"{}={}\"<\/span>, key, value));\n        }\n\n        <span class=\"hljs-comment\">\/\/ Step 2: Concatenate the sorted parameters and the API secret<\/span>\n        let string_to_sign = format!(<span class=\"hljs-string\">\"{}{}\"<\/span>, sorted_params, api_secret);\n\n        <span class=\"hljs-comment\">\/\/ Step 3: Generate an SHA-1 hash of the concatenated string<\/span>\n        let mut hasher = Sha1::new();\n        hasher.update(string_to_sign.as_bytes());\n\n        <span class=\"hljs-comment\">\/\/ Step 4: Return the hex-encoded result<\/span>\n        hex::encode(hasher.finalize())\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\"><strong>Save and Validate the Video File Upload&nbsp;<\/strong><\/h3>\n\n\n\n<p>Before uploading a video to Cloudinary, handle the file upload in your Rust backend. Create a function that saves the uploaded video to a temporary file, ensuring it is indeed a video file and doesn\u2019t exceed a specified size limit. This step is crucial for validating and preparing the file before it\u2019s processed or uploaded to Cloudinary.&nbsp;<\/p>\n\n\n\n<p>The backend system can handle various video file formats, such as MP4, WebM, and others supported by the MIME type validation. The video file is temporarily saved for validation and then uploaded to Cloudinary.<\/p>\n\n\n\n<p>Add the following code to implement video file validating and saving <em>to a temporary file<\/em>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">\n<span class=\"hljs-comment\">\/\/ src\/video_service.rs<\/span>\n<span class=\"hljs-comment\">\/\/...<\/span>\nimpl VideoService {\n    <span class=\"hljs-comment\">\/\/...<\/span>\n    pub <span class=\"hljs-keyword\">async<\/span> fn save_file(mut payload: Multipart) -&gt; Result&lt;NamedTempFile, <span class=\"hljs-built_in\">Error<\/span>&gt; {\n        <span class=\"hljs-keyword\">let<\/span> mut total_size = <span class=\"hljs-number\">0<\/span>;\n        <span class=\"hljs-keyword\">let<\/span> mut temp_file = NamedTempFile::<span class=\"hljs-keyword\">new<\/span>()?; <span class=\"hljs-comment\">\/\/ Create a temporary file<\/span>\n        <span class=\"hljs-comment\">\/\/ Iterate over multipart stream<\/span>\n        <span class=\"hljs-keyword\">while<\/span> <span class=\"hljs-keyword\">let<\/span> Some(field) = payload.next().await {\n            <span class=\"hljs-keyword\">let<\/span> mut field = field?;\n            <span class=\"hljs-keyword\">let<\/span> content_type = field.content_type(); <span class=\"hljs-comment\">\/\/ Get the MIME type of the file<\/span>\n            <span class=\"hljs-comment\">\/\/ Ensure content_type is present and it is a video<\/span>\n            <span class=\"hljs-keyword\">if<\/span> <span class=\"hljs-keyword\">let<\/span> Some(content_type) = content_type {\n                <span class=\"hljs-keyword\">if<\/span> content_type.type_() != mime::VIDEO {\n                    <span class=\"hljs-keyword\">return<\/span> Err(actix_web::error::ErrorBadRequest(\n                        <span class=\"hljs-string\">\"Only video files are allowed\"<\/span>,\n                    ));\n                }\n            } <span class=\"hljs-keyword\">else<\/span> {\n                <span class=\"hljs-keyword\">return<\/span> Err(actix_web::error::ErrorBadRequest(<span class=\"hljs-string\">\"Missing content type\"<\/span>));\n            }\n            <span class=\"hljs-comment\">\/\/ Write the file content to the temporary file synchronously<\/span>\n            <span class=\"hljs-keyword\">while<\/span> <span class=\"hljs-keyword\">let<\/span> Some(chunk) = field.next().await {\n                <span class=\"hljs-keyword\">let<\/span> data = chunk?;\n                total_size += data.len();\n                <span class=\"hljs-keyword\">if<\/span> total_size &gt; MAX_SIZE {\n                    <span class=\"hljs-keyword\">return<\/span> Err(actix_web::error::ErrorBadRequest(\n                        <span class=\"hljs-string\">\"File size limit exceeded\"<\/span>,\n                    ));\n                }\n                temp_file.write_all(&amp;data)?;\n            }\n        }\n        Ok(temp_file)\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h4 class=\"wp-block-heading\"><strong>Upload Video to Cloudinary<\/strong><\/h4>\n\n\n\n<p>After saving the video file locally in the prior step, the next task is to upload it to Cloudinary. Create a function that manages the upload process by generating a signed request to Cloudinary&#8217;s API. This function should read the file, create the required authentication parameters, and then send the video file to Cloudinary.<\/p>\n\n\n\n<p>Once the upload is complete, Cloudinary&#8217;s response will include the video URL, which you can store in a database or pass on to another service for further processing.<\/p>\n\n\n\n<p>Add the following code to implement the upload functionality:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-wrap-lines\">\n<span class=\"hljs-comment\">\/\/ src\/video_service.rs<\/span>\n<span class=\"hljs-comment\">\/\/...<\/span>\nimpl VideoService {\n    <span class=\"hljs-comment\">\/\/...<\/span>\n    pub async fn upload_to_cloudinary(\n        temp_file: &amp;NamedTempFile,\n    ) -&gt; Result&lt;CloudinaryResponse, Box&lt;dyn std::error::Error&gt;&gt; {\n        let client = Client::new();\n        let cloud_name = VideoService::env_loader(<span class=\"hljs-string\">\"CLOUDINARY_CLOUD_NAME\"<\/span>);\n        let api_secret = VideoService::env_loader(<span class=\"hljs-string\">\"CLOUDINARY_API_SECRET\"<\/span>);\n        let api_key = VideoService::env_loader(<span class=\"hljs-string\">\"CLOUDINARY_API_KEY\"<\/span>);\n        let timestamp = chrono::Utc::now().timestamp();\n        let public_id = temp_file\n            .path()\n            .file_name()\n            .and_then(|name| name.to_str())\n            .unwrap_or(<span class=\"hljs-string\">\"file\"<\/span>)\n            .to_string();\n        <span class=\"hljs-comment\">\/\/ Include only public_id and timestamp in the signature<\/span>\n        let mut params = HashMap::new();\n        params.insert(<span class=\"hljs-string\">\"public_id\"<\/span>, ParamValue::Str(public_id.to_string()));\n        params.insert(<span class=\"hljs-string\">\"timestamp\"<\/span>, ParamValue::Int(timestamp));\n        let signature = VideoService::generate_signature(params, &amp;api_secret);\n        let mut file = tokio::fs::File::open(temp_file.path()).await?;\n        let mut buffer = Vec::new();\n        file.read_to_end(&amp;mut buffer).await?;\n        let part = Part::bytes(buffer).file_name(public_id.<span class=\"hljs-keyword\">clone<\/span>());\n        let form = multipart::Form::new()\n            .text(<span class=\"hljs-string\">\"public_id\"<\/span>, public_id.<span class=\"hljs-keyword\">clone<\/span>())\n            .text(<span class=\"hljs-string\">\"timestamp\"<\/span>, timestamp.to_string())\n            .text(<span class=\"hljs-string\">\"signature\"<\/span>, signature)\n            .text(<span class=\"hljs-string\">\"api_key\"<\/span>, api_key)\n            .part(<span class=\"hljs-string\">\"file\"<\/span>, part);\n        let res = client\n            .post(format!(\n                <span class=\"hljs-string\">\"https:\/\/api.cloudinary.com\/v1_1\/{}\/video\/upload\"<\/span>,\n                cloud_name\n            ))\n            .multipart(form)\n            .send()\n            .await?;\n        let result = res.text().await?;\n        let cloudinary_response: CloudinaryResponse = serde_json::from_str(&amp;result)?;\n        Ok(cloudinary_response)\n    }\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h4 class=\"wp-block-heading\"><strong>Create the API Handler<\/strong><\/h4>\n\n\n\n<p>In the previous steps, you successfully implemented the API logic. Next, you need to create the handler, which is the endpoint that can receive requests from any client.&nbsp;<\/p>\n\n\n\n<p>Import the required dependencies in the handler file and create an <code>upload_video<\/code> function with a corresponding API route. This handler will use the services to perform the necessary actions and return the appropriate response using the <code>APIResponse<\/code> and <code>APIErrorResponse<\/code>. Create a file named <code>handler.rs<\/code> in the <code>src<\/code> folder and add the following code snippet:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-wrap-lines\">\n<span class=\"hljs-comment\">\/\/ src\/handler.rs<\/span>\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">actix_multipart<\/span>::<span class=\"hljs-title\">Multipart<\/span>;\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">actix_web<\/span>::{<span class=\"hljs-title\">post<\/span>, <span class=\"hljs-title\">Error<\/span>, <span class=\"hljs-title\">HttpResponse<\/span>};\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">reqwest<\/span>::<span class=\"hljs-title\">StatusCode<\/span>;\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">crate<\/span>::{\n    <span class=\"hljs-title\">models<\/span>::{<span class=\"hljs-title\">APIErrorResponse<\/span>, <span class=\"hljs-title\">APIResponse<\/span>, <span class=\"hljs-title\">CloudinaryResponse<\/span>},\n    <span class=\"hljs-title\">video_service<\/span>::<span class=\"hljs-title\">VideoService<\/span>,\n};\n<span class=\"hljs-comment\">#&#91;post(\"\/upload\")]<\/span>\npub async fn upload_video(multipart: Multipart) -&gt; Result&lt;HttpResponse, Error&gt; {\n    let file_path = VideoService::save_file(multipart).await?;\n    let upload_details = VideoService::upload_to_cloudinary(&amp;file_path).await;\n    match upload_details {\n        Ok(data) =&gt; Ok(HttpResponse::Created().json(APIResponse::&lt;CloudinaryResponse&gt; {\n            status: StatusCode::CREATED.as_u16(),\n            message: <span class=\"hljs-string\">\"success\"<\/span>.to_string(),\n            data: Some(data),\n        })),\n        Err(error) =&gt; Ok(HttpResponse::InternalServerError().json(APIErrorResponse {\n            status: StatusCode::INTERNAL_SERVER_ERROR.as_u16(),\n            message: <span class=\"hljs-string\">\"failure\"<\/span>.to_string(),\n            data: Some(error.to_string()),\n        })),\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\"><strong>Update <code>main.rs<\/code><\/strong><\/h3>\n\n\n\n<p>Update the main.rs file to include your application entry point and use the handler to set up the server with the following code.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-wrap-lines\">\n<span class=\"hljs-comment\">\/\/ src\/main.rs<\/span>\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">actix_web<\/span>::{<span class=\"hljs-title\">App<\/span>, <span class=\"hljs-title\">HttpServer<\/span>};\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">handler<\/span>::<span class=\"hljs-title\">upload_video<\/span>;\nmod handler;\nmod models;\nmod video_service;\n\n<span class=\"hljs-comment\">#&#91;actix_web::main]<\/span>\nasync fn main() -&gt; std::io::Result&lt;()&gt; {\n    HttpServer::new(|| App::new().service(upload_video))\n        .bind(<span class=\"hljs-string\">\"127.0.0.1:8080\"<\/span>)?\n        .run()\n        .await\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Next, start the development server using the command below:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs shcb-wrap-lines\">cargo run<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\"><div><h2 data-usually-unique-id=\"616026814914499887617885\"><span class=\" author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qowz82z5wgz81zxaz66znz70zuoz68znz69zz84zz71zscau1fz86znsoniz88zy\">Test the Application<\/span><\/h2><\/div><\/h2>\n\n\n\n<p><div><span class=\" author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qotvoyjz86zz89zaz72zz89zz80zz76zz88zz67zz72zvz87zz89z1z88zdkloz88zbz73zz86zz77zxqz74z\">Congratulations! It&#8217;s time to test the application by uploading a video. This tutorial shows you how to use Postman, but feel free to use any other API testing platform of your choice. Open your Postman and enter the URL <span style=\"font-family: monospace; background-color: rgb(247, 249, 250); color: rgb(27, 39, 51); border: 1px solid rgba(208, 212, 217, 0.5); margin-left: -1px;\"><code>http:\/\/localhost:8080\/upload<\/code><\/span>. Then, test the application by uploading a video of your choice that is less than 10 MB, as shown below.<\/span><\/div><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img width=\"1024\" height=\"604\" data-public-id=\"Web_Assets\/blog\/blog-How-to-Upload-a-Video-in-a-Rust-Backend-2\/blog-How-to-Upload-a-Video-in-a-Rust-Backend-2.png\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/w_1024,h_604,c_scale\/f_auto,q_auto\/v1724098396\/Web_Assets\/blog\/blog-How-to-Upload-a-Video-in-a-Rust-Backend-2\/blog-How-to-Upload-a-Video-in-a-Rust-Backend-2.png?_i=AA\" alt=\"\" class=\"wp-post-35313 wp-image-35315\" data-format=\"png\" data-transformations=\"f_auto,q_auto\" data-version=\"1724098396\" data-seo=\"1\" srcset=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1724098396\/Web_Assets\/blog\/blog-How-to-Upload-a-Video-in-a-Rust-Backend-2\/blog-How-to-Upload-a-Video-in-a-Rust-Backend-2.png?_i=AA 1600w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1724098396\/Web_Assets\/blog\/blog-How-to-Upload-a-Video-in-a-Rust-Backend-2\/blog-How-to-Upload-a-Video-in-a-Rust-Backend-2.png?_i=AA 300w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1724098396\/Web_Assets\/blog\/blog-How-to-Upload-a-Video-in-a-Rust-Backend-2\/blog-How-to-Upload-a-Video-in-a-Rust-Backend-2.png?_i=AA 768w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1724098396\/Web_Assets\/blog\/blog-How-to-Upload-a-Video-in-a-Rust-Backend-2\/blog-How-to-Upload-a-Video-in-a-Rust-Backend-2.png?_i=AA 1024w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1724098396\/Web_Assets\/blog\/blog-How-to-Upload-a-Video-in-a-Rust-Backend-2\/blog-How-to-Upload-a-Video-in-a-Rust-Backend-2.png?_i=AA 1536w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>After uploading the video, you should receive a response indicating a successful upload, along with details about the video file. This confirms that your Rust backend and Cloudinary integration are working correctly.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>This blog post shows you how to upload a video in the Rust backend with Cloudinary. You can also use the same approach for image uploads but with different specifications from video uploads. To learn more about how Cloudinary allows developers to upload, store, manage, optimize, and deliver images and videos, <a target=\"_blank\" href=\"https:\/\/cloudinary.com\/\" rel=\"noreferrer noopener\">contact us today<\/a>.<\/p>\n\n\n\n<p>If you found this blog post helpful and want to discuss it more, head over to the <a target=\"_blank\" href=\"https:\/\/community.cloudinary.com\/\" rel=\"noreferrer noopener\">Cloudinary Community forum<\/a> and its associated <a target=\"_blank\" href=\"https:\/\/discord.com\/invite\/cloudinary\" rel=\"noreferrer noopener\">Discord<\/a>. We\u2019d love to hear about your projects, experiences, and challenges.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Resources<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/cloudinary.com\/documentation\/image_upload_api_reference\" target=\"_blank\" rel=\"noreferrer noopener\">Cloudinary Upload API<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/cloudinary.com\/documentation\/authentication_signatures\" target=\"_blank\" rel=\"noreferrer noopener\">Generating authentication signatures<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/actix.rs\" target=\"_blank\" rel=\"noreferrer noopener\">Actix web framework<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Uploading videos is a common requirement for modern web applications, and handling this functionality efficiently on the server side is important. Rust&#8216;s performance and safety features are an excellent choice for backend development, while Cloudinary offers powerful cloud-based media management solutions. This blog post will guide you through uploading a video in a Rust backend [&hellip;]<\/p>\n","protected":false},"author":87,"featured_media":35317,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_cloudinary_featured_overwrite":false,"footnotes":""},"categories":[1],"tags":[25,305],"class_list":["post-35313","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-asset-management","tag-video-api"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.6 (Yoast SEO v26.9) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>How to Upload a Video in a Rust Backend<\/title>\n<meta name=\"description\" content=\"Master video uploads in Rust with our Cloudinary tutorial. Includes project setup, API service creation, and file validation.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/cloudinary.com\/blog\/how-to-upload-a-video-in-a-rust-backend\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How to Upload a Video in a Rust Backend\" \/>\n<meta property=\"og:description\" content=\"Master video uploads in Rust with our Cloudinary tutorial. Includes project setup, API service creation, and file validation.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudinary.com\/blog\/how-to-upload-a-video-in-a-rust-backend\" \/>\n<meta property=\"og:site_name\" content=\"Cloudinary Blog\" \/>\n<meta property=\"article:published_time\" content=\"2024-08-23T14:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-03-30T09:26:59+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/v1723847900\/uploading_videos_with_Rust-blog\/uploading_videos_with_Rust-blog-jpg?_i=AA\" \/>\n\t<meta property=\"og:image:width\" content=\"2000\" \/>\n\t<meta property=\"og:image:height\" content=\"1100\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"melindapham\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"NewsArticle\",\"@id\":\"https:\/\/cloudinary.com\/blog\/how-to-upload-a-video-in-a-rust-backend#article\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/how-to-upload-a-video-in-a-rust-backend\"},\"author\":{\"name\":\"melindapham\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9\"},\"headline\":\"How to Upload a Video in a Rust Backend\",\"datePublished\":\"2024-08-23T14:00:00+00:00\",\"dateModified\":\"2025-03-30T09:26:59+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/how-to-upload-a-video-in-a-rust-backend\"},\"wordCount\":1190,\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/how-to-upload-a-video-in-a-rust-backend#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1723847900\/uploading_videos_with_Rust-blog\/uploading_videos_with_Rust-blog.jpg?_i=AA\",\"keywords\":[\"Asset Management\",\"Video API\"],\"inLanguage\":\"en-US\",\"copyrightYear\":\"2024\",\"copyrightHolder\":{\"@id\":\"https:\/\/cloudinary.com\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudinary.com\/blog\/how-to-upload-a-video-in-a-rust-backend\",\"url\":\"https:\/\/cloudinary.com\/blog\/how-to-upload-a-video-in-a-rust-backend\",\"name\":\"How to Upload a Video in a Rust Backend\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/how-to-upload-a-video-in-a-rust-backend#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/how-to-upload-a-video-in-a-rust-backend#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1723847900\/uploading_videos_with_Rust-blog\/uploading_videos_with_Rust-blog.jpg?_i=AA\",\"datePublished\":\"2024-08-23T14:00:00+00:00\",\"dateModified\":\"2025-03-30T09:26:59+00:00\",\"description\":\"Master video uploads in Rust with our Cloudinary tutorial. Includes project setup, API service creation, and file validation.\",\"breadcrumb\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/how-to-upload-a-video-in-a-rust-backend#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudinary.com\/blog\/how-to-upload-a-video-in-a-rust-backend\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/how-to-upload-a-video-in-a-rust-backend#primaryimage\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1723847900\/uploading_videos_with_Rust-blog\/uploading_videos_with_Rust-blog.jpg?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1723847900\/uploading_videos_with_Rust-blog\/uploading_videos_with_Rust-blog.jpg?_i=AA\",\"width\":2000,\"height\":1100},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudinary.com\/blog\/how-to-upload-a-video-in-a-rust-backend#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudinary.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"How to Upload a Video in a Rust Backend\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"name\":\"Cloudinary Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/cloudinary.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\",\"name\":\"Cloudinary Blog\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"width\":312,\"height\":60,\"caption\":\"Cloudinary Blog\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9\",\"name\":\"melindapham\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g\",\"caption\":\"melindapham\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"How to Upload a Video in a Rust Backend","description":"Master video uploads in Rust with our Cloudinary tutorial. Includes project setup, API service creation, and file validation.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/cloudinary.com\/blog\/how-to-upload-a-video-in-a-rust-backend","og_locale":"en_US","og_type":"article","og_title":"How to Upload a Video in a Rust Backend","og_description":"Master video uploads in Rust with our Cloudinary tutorial. Includes project setup, API service creation, and file validation.","og_url":"https:\/\/cloudinary.com\/blog\/how-to-upload-a-video-in-a-rust-backend","og_site_name":"Cloudinary Blog","article_published_time":"2024-08-23T14:00:00+00:00","article_modified_time":"2025-03-30T09:26:59+00:00","og_image":[{"width":2000,"height":1100,"url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/v1723847900\/uploading_videos_with_Rust-blog\/uploading_videos_with_Rust-blog-jpg?_i=AA","type":"image\/jpeg"}],"author":"melindapham","twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"NewsArticle","@id":"https:\/\/cloudinary.com\/blog\/how-to-upload-a-video-in-a-rust-backend#article","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/how-to-upload-a-video-in-a-rust-backend"},"author":{"name":"melindapham","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9"},"headline":"How to Upload a Video in a Rust Backend","datePublished":"2024-08-23T14:00:00+00:00","dateModified":"2025-03-30T09:26:59+00:00","mainEntityOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/how-to-upload-a-video-in-a-rust-backend"},"wordCount":1190,"publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/how-to-upload-a-video-in-a-rust-backend#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1723847900\/uploading_videos_with_Rust-blog\/uploading_videos_with_Rust-blog.jpg?_i=AA","keywords":["Asset Management","Video API"],"inLanguage":"en-US","copyrightYear":"2024","copyrightHolder":{"@id":"https:\/\/cloudinary.com\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/how-to-upload-a-video-in-a-rust-backend","url":"https:\/\/cloudinary.com\/blog\/how-to-upload-a-video-in-a-rust-backend","name":"How to Upload a Video in a Rust Backend","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/how-to-upload-a-video-in-a-rust-backend#primaryimage"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/how-to-upload-a-video-in-a-rust-backend#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1723847900\/uploading_videos_with_Rust-blog\/uploading_videos_with_Rust-blog.jpg?_i=AA","datePublished":"2024-08-23T14:00:00+00:00","dateModified":"2025-03-30T09:26:59+00:00","description":"Master video uploads in Rust with our Cloudinary tutorial. Includes project setup, API service creation, and file validation.","breadcrumb":{"@id":"https:\/\/cloudinary.com\/blog\/how-to-upload-a-video-in-a-rust-backend#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudinary.com\/blog\/how-to-upload-a-video-in-a-rust-backend"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/how-to-upload-a-video-in-a-rust-backend#primaryimage","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1723847900\/uploading_videos_with_Rust-blog\/uploading_videos_with_Rust-blog.jpg?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1723847900\/uploading_videos_with_Rust-blog\/uploading_videos_with_Rust-blog.jpg?_i=AA","width":2000,"height":1100},{"@type":"BreadcrumbList","@id":"https:\/\/cloudinary.com\/blog\/how-to-upload-a-video-in-a-rust-backend#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudinary.com\/blog\/"},{"@type":"ListItem","position":2,"name":"How to Upload a Video in a Rust Backend"}]},{"@type":"WebSite","@id":"https:\/\/cloudinary.com\/blog\/#website","url":"https:\/\/cloudinary.com\/blog\/","name":"Cloudinary Blog","description":"","publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/cloudinary.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/cloudinary.com\/blog\/#organization","name":"Cloudinary Blog","url":"https:\/\/cloudinary.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","width":312,"height":60,"caption":"Cloudinary Blog"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9","name":"melindapham","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g","caption":"melindapham"}}]}},"jetpack_featured_media_url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1723847900\/uploading_videos_with_Rust-blog\/uploading_videos_with_Rust-blog.jpg?_i=AA","_links":{"self":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/35313","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/users\/87"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/comments?post=35313"}],"version-history":[{"count":2,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/35313\/revisions"}],"predecessor-version":[{"id":37300,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/35313\/revisions\/37300"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media\/35317"}],"wp:attachment":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media?parent=35313"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/categories?post=35313"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/tags?post=35313"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}