{"id":21530,"date":"2017-05-24T16:04:36","date_gmt":"2017-05-24T16:04:36","guid":{"rendered":"http:\/\/serverless_tutorial_file_storage_with_webtask_and_cloudinary"},"modified":"2024-10-01T13:01:04","modified_gmt":"2024-10-01T20:01:04","slug":"serverless_tutorial_file_storage_with_webtask_and_cloudinary","status":"publish","type":"post","link":"https:\/\/cloudinary.com\/blog\/serverless_tutorial_file_storage_with_webtask_and_cloudinary","title":{"rendered":"Serverless Tutorial: File Storage with Webtask and Cloudinary"},"content":{"rendered":"<div class=\"wp-block-cloudinary-markdown \"><p>Media makes up the majority of today\u2019s website content. While it makes websites more interesting for visitors, media presents challenges because these images and videos are more difficult to store, deliver and manipulate on-the-fly to suit any given situation.<\/p>\n<p>One particularly challenging topic is <strong>storage<\/strong>. Traditionally &#8211; before the cloud era &#8211; FTP was the the go-to solution. We relied on FTP for transferring files to our remote computers. These files are mapped to a URL that we could just deliver to the browser.<\/p>\n<p>What if you have hundreds of images of varying quality and size that need to be stored and delivered. If you do not carefully manage them, storing these files could become difficult, which could lead to unforeseen complexities.<\/p>\n<p>The introduction of cloud storage and hosting helped address the storage problem. Notwithstanding, the cloud (and DevOps engineering generally) still remain a mystery for those of us developers who just write code.<\/p>\n<p>This mystery, however, is about to be solved. <strong>Today, we are going to attempt to go completely serverless by deploying Functions to Webtask and storing media files on Cloudinary<\/strong>.<\/p>\n<h2>Why Serverless<\/h2>\n<p>The term serverless does not imply that servers will no longer exist. Rather, it implies that we, the developers, no longer have to care about their existence. We won\u2019t have to set anything up, or bother about IP address and all those terms (like load balancing, containers, etc) that we aren\u2019t accustomed to. We will be able to write and ship functions, as well as upload images to an existing server, for free by creating a Cloudinary account.<\/p>\n<p>Let\u2019s now look in more detail about why you may want to consider this serverless option:<\/p>\n<blockquote>\n<p>\u201cServerless\u201d in this article refers to both deployable functions (Function as a Service) and cloud platforms (aka Backend as a Service) like Cloudinary<\/p>\n<\/blockquote>\n<ul>\n<li>\n<strong>Affordability<\/strong>: Not just serverless, but generally, PaaS, SaaS, IaaS, and *aaS are affordable on a large scale when compared to the cost of doing it yourself. In fact, on a small scale, most services are made free, much like <a href=\"#\">Cloudinary<\/a>\n<\/li>\n<li>\n<strong>Risk Free<\/strong>: Managing backups, security and other sensitive aspects of your project lifecycle shouldn\u2019t be something you have to worry about. As a developer, your sole job is to write code, so you can focus on that while the platforms take care of these other tasks.<\/li>\n<li>Taking the serverless route enables you to focus on what matters in your development cycle as a developer. Sticking to your job of writing code and using simple APIs to store and ship code\/assets.<\/li>\n<\/ul>\n<h2>Hosting Functions with Webtask<\/h2>\n<p>To get started, let\u2019s create a <strong>Hello World<\/strong> example with Webtask and see how simple it is.<\/p>\n<p>To do so, we need to install the Webtask CLI tool. The tool requires an account with Webtask so we can create one before installation:<\/p>\n<pre class=\"js-syntax-highlighted\"><span><code class=\"hljs shcb-wrap-lines\">npm install wt-cli -g\n<\/code><\/span><\/pre>\n<p>Login to the CLI using your sign-up email address:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\">wt init <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Your<\/span> <span class=\"hljs-attr\">Email<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Create an <code>index.js<\/code> file with the following Function as a Service:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-built_in\">module<\/span>.exports = <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> (<span class=\"hljs-params\">cb<\/span>) <\/span>{\n\tcb(<span class=\"hljs-literal\">null<\/span>, <span class=\"hljs-string\">'Hello World'<\/span>);\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><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<p>Deploy and run your function:<\/p>\n<pre class=\"js-syntax-highlighted\" 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\">wt<\/span> <span class=\"hljs-selector-tag\">create<\/span> <span class=\"hljs-selector-tag\">index<\/span><span class=\"hljs-selector-class\">.js<\/span>\n<\/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<p>Amazing! You have a deployed your app, which now runs on the Webtask server. Go to the URL logged to your console after running the last command to see your deployed app running.<\/p>\n<p>Two things you might want to take note of:<\/p>\n<ol>\n<li>We just wrote a <strong>function<\/strong>. A function that takes a callback and sends content as a response. You could already imagine the power.<\/li>\n<li>The <code>create<\/code> command deploys our app (function) and serves us a <strong>URL<\/strong> to interact with.<\/li>\n<\/ol>\n<p>Let\u2019s employ <a href=\"https:\/\/expressjs.com\">Express<\/a> to make endpoints which you might be more familiar with:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-comment\">\/\/ .\/index.js<\/span>\n<span class=\"hljs-keyword\">var<\/span> Express = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">'express'<\/span>);\n<span class=\"hljs-keyword\">var<\/span> Webtask = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">'webtask-tools'<\/span>);\n<span class=\"hljs-keyword\">var<\/span> bodyParser = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">'body-parser'<\/span>)\n<span class=\"hljs-keyword\">var<\/span> app = Express();\n\napp.use(bodyParser.urlencoded({ <span class=\"hljs-attr\">extended<\/span>: <span class=\"hljs-literal\">false<\/span> }))\napp.use(bodyParser.json())\n\n<span class=\"hljs-comment\">\/\/ yet to be created<\/span>\napp.use(<span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">'.\/middleware\/cl'<\/span>).config);\n<span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">'.\/routes\/galleries'<\/span>)(app);\n\n<span class=\"hljs-built_in\">module<\/span>.exports = Webtask.fromExpress(app);\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><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<p>Endeavour to install the dependencies: <code>express<\/code>, <code>webtask-tools<\/code>,  and <code>body-parser<\/code>.<\/p>\n<ul>\n<li>\n<p><code>express<\/code> is a fast Node framework for handling HTTP requests\/responses<\/p>\n<\/li>\n<li>\n<p><code>body-parser<\/code> parses the HTTP request body and exposes it to express <code>req.body<\/code><\/p>\n<\/li>\n<li>\n<p><code>webtask-tools<\/code> simplifies integrating Express and Webtask. No need for the previous function we wrote, we can now write Express routes instead.<\/p>\n<\/li>\n<\/ul>\n<p>Let\u2019s create the routes:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-comment\">\/\/ .\/routes\/galleries.js<\/span>\n\n<span class=\"hljs-built_in\">module<\/span>.exports = <span class=\"hljs-function\">(<span class=\"hljs-params\">app<\/span>) =&gt;<\/span> {\n  app.get(<span class=\"hljs-string\">'\/images'<\/span>, (req, res) =&gt; {\n      res.json({<span class=\"hljs-attr\">msg<\/span>: <span class=\"hljs-string\">'Images are coming soon'<\/span>})\n  });\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><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<h2>Storing and Delivering Images with Cloudinary<\/h2>\n<p>Our next major concern is that Webtask might do a great job at hosting functions, but it may be terrible at file storage, especially media files. Therefore, we need a media storage solution to take care of this for us. Cloudinary offers media storage, but that\u2019s not where it shines.<\/p>\n<p>Cloudinary is a media server that manages your media storage and delivery. What\u2019s most impressive is Cloudinary\u2019s  ability to transform these media during upload or delivery by simply adjusting the image\u2019s delivery URL. Using Cloudinary, you can specify width, height, filters, overlays, and enable a lot of other cool features by editing an image\/video transformation URL, which you can learn about <a href=\"https:\/\/cloudinary.com\/documentation\/image_transformations\">here<\/a>.<\/p>\n<p>To use Cloudinary effectively, we recommend using the SDKs rather than interact with the APIs directly (which you are allowed to do). You can install the SDK to your current project:<\/p>\n<pre class=\"js-syntax-highlighted\"><span><code class=\"hljs shcb-wrap-lines\">npm install --save cloudinary_js\n<\/code><\/span><\/pre>\n<p>You also need to create a <a href=\"https:\/\/cloudinary.com\/users\/register\/free\">FREE Cloudinary account<\/a> to get credentials that you will supply to the SDK in order to interact with Cloudinary.<\/p>\n<h3>Configuring Cloudinary with Webtask Context<\/h3>\n<p>Webtask allows you to dynamically adjust its behavior based on the information provided via the Webtask context. We could use the context to maintain dynamic state of our application. Things like query parameters, secrets and environmental variables are a good fit for what could live in the Webtask context. Speaking of environmental variables, let\u2019s rely on those to configure Cloudinary:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-comment\">\/\/ .\/middlewares\/cl.js<\/span>\n<span class=\"hljs-keyword\">var<\/span> cloudinary = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">'cloudinary'<\/span>);\n\n<span class=\"hljs-built_in\">module<\/span>.exports = {\n    <span class=\"hljs-attr\">config<\/span>: <span class=\"hljs-function\">(<span class=\"hljs-params\">req, res, next<\/span>) =&gt;<\/span> {\n        cloudinary.config({\n            <span class=\"hljs-attr\">cloud_name<\/span>: req.webtaskContext.secrets.CL_CLOUD_NAME,\n            <span class=\"hljs-attr\">api_key<\/span>: req.webtaskContext.secrets.CL_API_KEY,\n            <span class=\"hljs-attr\">api_secret<\/span>: req.webtaskContext.secrets.CL_SECRET\n        });\n        req.cloudinary = cloudinary;\n        next()\n    },\n}\n<\/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<p>A simple Express middleware that configures an instance of <code>cloudinary<\/code> using credentials provisioned via the Webtask Context Secret. While running the functions, you are expected to supply the credentials:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\">wt create index --secret CL_CLOUD_NAME=<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">CLOURINARY_CLOUD_NAME<\/span>&gt;<\/span> --secret CL_API_KEY=<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">CLOURINARY_API_KEY<\/span>&gt;<\/span> --secret CL_SECRET=<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">CLOURINARY_API_SECRET<\/span>&gt;<\/span> --bundle --watch\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Remember to fetch the credentials from your <a href=\"https:\/\/cloudinary.com\/users\/login\">Cloudinary dashboard<\/a>.<\/p>\n<p>Notice how we are passing each credential using the <code>--secret<\/code> option, as well as telling Webtask to bundle our file and watch for changes using <code>--bundle<\/code> and <code>--watch<\/code> flags, respectively. Bundling is only necessary when you have multiple local modules.<\/p>\n<h3>Uploading Images to Cloudinary<\/h3>\n<p>Now that we have everything configured, let\u2019s store our image on Cloudinary by uploading it from our computers. We can do this by adding an endpoint that its logic will process the image and send it to Cloudinary using the SDK:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-comment\">\/\/ .\/routes\/galleries.js<\/span>\n<span class=\"hljs-keyword\">var<\/span> multipart = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">'connect-multiparty'<\/span>);\n<span class=\"hljs-keyword\">var<\/span> multipartMiddleware = multipart();\n\n<span class=\"hljs-built_in\">module<\/span>.exports = <span class=\"hljs-function\">(<span class=\"hljs-params\">app<\/span>) =&gt;<\/span> {\n\t...\n\tapp.post(<span class=\"hljs-string\">'\/images'<\/span>, multipartMiddleware, (req, res) =&gt; {\n\t    <span class=\"hljs-built_in\">console<\/span>.log(req.files)\n\t      req.cloudinary.uploader.upload(req.files.image.path, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span>(<span class=\"hljs-params\">result<\/span>) <\/span>{\n\t         res.status(<span class=\"hljs-number\">200<\/span>).send(<span class=\"hljs-string\">'Image uploaded to Cloudinary'<\/span>)\n\t     });\n\t })\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\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>When the image arrives from the client, it is parsed and processed with <code>multipart<\/code> and uploaded to Cloudinary using the <code>upload<\/code> method. Remember that <code>req.cloudinary<\/code> is provided via the middleware we created earlier.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/cloudinary-res.cloudinary.com\/image\/upload\/w_700,c_fill\/ggVQdlz.png\" alt=\"Serverless\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"700\" height=\"406\"\/><\/p>\n<p><a href=\"https:\/\/github.com\/christiannwamba\/hack-ng-api\">Source Code<\/a><\/p>\n<p>Notice how stayed away from creating any local host\/server and built everything using the actual environment that our code and media will live. This is where the power of serverless lies.<\/p>\n<p>Cloudinary exposes lots of APIs and transformation options that you can learn about in the <a href=\"https:\/\/cloudinary.com\/documentation\">documentation<\/a>. Feel free to dig these docs and find what suits your situation.<\/p>\n<\/div>","protected":false},"excerpt":{"rendered":"","protected":false},"author":41,"featured_media":21531,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_cloudinary_featured_overwrite":false,"footnotes":""},"categories":[1],"tags":[53,134],"class_list":["post-21530","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-cloud-storage","tag-guest-post"],"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>Serverless Tutorial: File Storage with Webtask and Cloudinary<\/title>\n<meta name=\"description\" content=\"Serverless Tutorial: How to deploy a serverless app while managing your media.\" \/>\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\/serverless_tutorial_file_storage_with_webtask_and_cloudinary\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Serverless Tutorial: File Storage with Webtask and Cloudinary\" \/>\n<meta property=\"og:description\" content=\"Serverless Tutorial: How to deploy a serverless app while managing your media.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudinary.com\/blog\/serverless_tutorial_file_storage_with_webtask_and_cloudinary\" \/>\n<meta property=\"og:site_name\" content=\"Cloudinary Blog\" \/>\n<meta property=\"article:published_time\" content=\"2017-05-24T16:04:36+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-10-01T20:01:04+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/v1649724310\/Web_Assets\/blog\/Serverless_215315bf17\/Serverless_215315bf17-png?_i=AA\" \/>\n\t<meta property=\"og:image:width\" content=\"1540\" \/>\n\t<meta property=\"og:image:height\" content=\"847\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\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\/serverless_tutorial_file_storage_with_webtask_and_cloudinary#article\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/serverless_tutorial_file_storage_with_webtask_and_cloudinary\"},\"author\":{\"name\":\"\",\"@id\":\"\"},\"headline\":\"Serverless Tutorial: File Storage with Webtask and Cloudinary\",\"datePublished\":\"2017-05-24T16:04:36+00:00\",\"dateModified\":\"2024-10-01T20:01:04+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/serverless_tutorial_file_storage_with_webtask_and_cloudinary\"},\"wordCount\":8,\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/serverless_tutorial_file_storage_with_webtask_and_cloudinary#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649724310\/Web_Assets\/blog\/Serverless_215315bf17\/Serverless_215315bf17.png?_i=AA\",\"keywords\":[\"Cloud Storage\",\"Guest Post\"],\"inLanguage\":\"en-US\",\"copyrightYear\":\"2017\",\"copyrightHolder\":{\"@id\":\"https:\/\/cloudinary.com\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudinary.com\/blog\/serverless_tutorial_file_storage_with_webtask_and_cloudinary\",\"url\":\"https:\/\/cloudinary.com\/blog\/serverless_tutorial_file_storage_with_webtask_and_cloudinary\",\"name\":\"Serverless Tutorial: File Storage with Webtask and Cloudinary\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/serverless_tutorial_file_storage_with_webtask_and_cloudinary#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/serverless_tutorial_file_storage_with_webtask_and_cloudinary#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649724310\/Web_Assets\/blog\/Serverless_215315bf17\/Serverless_215315bf17.png?_i=AA\",\"datePublished\":\"2017-05-24T16:04:36+00:00\",\"dateModified\":\"2024-10-01T20:01:04+00:00\",\"description\":\"Serverless Tutorial: How to deploy a serverless app while managing your media.\",\"breadcrumb\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/serverless_tutorial_file_storage_with_webtask_and_cloudinary#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudinary.com\/blog\/serverless_tutorial_file_storage_with_webtask_and_cloudinary\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/serverless_tutorial_file_storage_with_webtask_and_cloudinary#primaryimage\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649724310\/Web_Assets\/blog\/Serverless_215315bf17\/Serverless_215315bf17.png?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649724310\/Web_Assets\/blog\/Serverless_215315bf17\/Serverless_215315bf17.png?_i=AA\",\"width\":1540,\"height\":847},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudinary.com\/blog\/serverless_tutorial_file_storage_with_webtask_and_cloudinary#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudinary.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Serverless Tutorial: File Storage with Webtask and Cloudinary\"}]},{\"@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\":\"\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Serverless Tutorial: File Storage with Webtask and Cloudinary","description":"Serverless Tutorial: How to deploy a serverless app while managing your media.","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\/serverless_tutorial_file_storage_with_webtask_and_cloudinary","og_locale":"en_US","og_type":"article","og_title":"Serverless Tutorial: File Storage with Webtask and Cloudinary","og_description":"Serverless Tutorial: How to deploy a serverless app while managing your media.","og_url":"https:\/\/cloudinary.com\/blog\/serverless_tutorial_file_storage_with_webtask_and_cloudinary","og_site_name":"Cloudinary Blog","article_published_time":"2017-05-24T16:04:36+00:00","article_modified_time":"2024-10-01T20:01:04+00:00","og_image":[{"width":1540,"height":847,"url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/v1649724310\/Web_Assets\/blog\/Serverless_215315bf17\/Serverless_215315bf17-png?_i=AA","type":"image\/png"}],"twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"NewsArticle","@id":"https:\/\/cloudinary.com\/blog\/serverless_tutorial_file_storage_with_webtask_and_cloudinary#article","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/serverless_tutorial_file_storage_with_webtask_and_cloudinary"},"author":{"name":"","@id":""},"headline":"Serverless Tutorial: File Storage with Webtask and Cloudinary","datePublished":"2017-05-24T16:04:36+00:00","dateModified":"2024-10-01T20:01:04+00:00","mainEntityOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/serverless_tutorial_file_storage_with_webtask_and_cloudinary"},"wordCount":8,"publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/serverless_tutorial_file_storage_with_webtask_and_cloudinary#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649724310\/Web_Assets\/blog\/Serverless_215315bf17\/Serverless_215315bf17.png?_i=AA","keywords":["Cloud Storage","Guest Post"],"inLanguage":"en-US","copyrightYear":"2017","copyrightHolder":{"@id":"https:\/\/cloudinary.com\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/serverless_tutorial_file_storage_with_webtask_and_cloudinary","url":"https:\/\/cloudinary.com\/blog\/serverless_tutorial_file_storage_with_webtask_and_cloudinary","name":"Serverless Tutorial: File Storage with Webtask and Cloudinary","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/serverless_tutorial_file_storage_with_webtask_and_cloudinary#primaryimage"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/serverless_tutorial_file_storage_with_webtask_and_cloudinary#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649724310\/Web_Assets\/blog\/Serverless_215315bf17\/Serverless_215315bf17.png?_i=AA","datePublished":"2017-05-24T16:04:36+00:00","dateModified":"2024-10-01T20:01:04+00:00","description":"Serverless Tutorial: How to deploy a serverless app while managing your media.","breadcrumb":{"@id":"https:\/\/cloudinary.com\/blog\/serverless_tutorial_file_storage_with_webtask_and_cloudinary#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudinary.com\/blog\/serverless_tutorial_file_storage_with_webtask_and_cloudinary"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/serverless_tutorial_file_storage_with_webtask_and_cloudinary#primaryimage","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649724310\/Web_Assets\/blog\/Serverless_215315bf17\/Serverless_215315bf17.png?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649724310\/Web_Assets\/blog\/Serverless_215315bf17\/Serverless_215315bf17.png?_i=AA","width":1540,"height":847},{"@type":"BreadcrumbList","@id":"https:\/\/cloudinary.com\/blog\/serverless_tutorial_file_storage_with_webtask_and_cloudinary#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudinary.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Serverless Tutorial: File Storage with Webtask and Cloudinary"}]},{"@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":""}]}},"jetpack_featured_media_url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649724310\/Web_Assets\/blog\/Serverless_215315bf17\/Serverless_215315bf17.png?_i=AA","_links":{"self":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/21530","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\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/comments?post=21530"}],"version-history":[{"count":5,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/21530\/revisions"}],"predecessor-version":[{"id":35795,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/21530\/revisions\/35795"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media\/21531"}],"wp:attachment":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media?parent=21530"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/categories?post=21530"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/tags?post=21530"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}