Skip to content
  • English Deutsch

benjamin-abt.com

Performance is a feature | Cloud - AI - Azure - .NET - Sustainability

  • Home
  • Blog
  • Portfolio
    • Overview
    • Workshops & Training
    • Publications
  • Contact
  • Home
  • Blog

Upload to Azure Storage with PHP

Upload to Azure Storage with PHP
May 7, 2019 3 min read BEN ABT
Azure

This article was written in 2019. Versions, tools and recommendations may have changed since then. Newer posts are collected under Azure.

I had the wonderful task to change a 20 year old PHP software during a Lift-and-Shift migration to Azure, so that it doesn’t store files directly in the web folder anymore, but uploads them to an Azure Blob Storage.

Dependencies

Microsoft provides a PHP SDK, with which the whole task can be done with a few lines of code. Only an additional component for identifying the mime type by the file extension is necessary.

You can use the PHP Composer to reference those dependencies

  • microsoft/azure-storage-blob
  • ralouphie/mimey

All settings are provided as environment vars.

  • STORAGE_ACCOUNT_NAME: your Azure Storage account name
  • STORAGE_ACCOUNT_KEY: your Azure Storage account key (secret)

The target storage container will be passed to the functions.

  1<?php
  2
  3# reference autoload
  4require_once(realpath($_SERVER["DOCUMENT_ROOT"]) . '/vendor/autoload.php');
  5
  6# imports
  7use MicrosoftAzure\Storage\Blob\Models\CreateBlockBlobOptions;
  8use MicrosoftAzure\Storage\Blob\BlobRestProxy;
  9
 10## adds file to the storage. Usage: storageAddFile("myContainer", "C:\path\to\file.png", "filename-on-storage.png")
 11function storageAddFile($containerName, $file, $fileName)
 12{
 13    # Setup a specific instance of an Azure::Storage::Client
 14    $connectionString = "DefaultEndpointsProtocol=https;AccountName=".getenv('STORAGE_ACCOUNT_NAME').";AccountKey=".getenv('STORAGE_ACCOUNT_KEY');
 15    // Create blob client.
 16    $blobClient = BlobRestProxy::createBlobService($connectionString);
 17
 18    $handle = @fopen($file, "r");
 19    if($handle)
 20    {
 21        $options = new CreateBlockBlobOptions();
 22        $mime = NULL;
 23
 24        try
 25        {
 26            // identify mime type
 27            $mimes = new \Mimey\MimeTypes;
 28            $mime = $mimes->getMimeType(pathinfo($fileName, PATHINFO_EXTENSION));
 29            // set content type
 30            $options->setContentType($mime);
 31        }
 32        catch ( Exception $e )
 33        {
 34            error_log("Failed to read mime from '".$file.": ". $e);
 35        } 
 36
 37        try
 38        {
 39            if($mime)
 40            {
 41                $cacheTime = getCacheTimeByMimeType($mime);
 42                if($cacheTime)
 43                {
 44                    $options->setCacheControl("public, max-age=".$cacheTime);
 45                }
 46            }
 47
 48            $blobClient->createBlockBlob($containerName, $fileName, $handle, $options);
 49        } catch ( Exception $e ) {
 50            error_log("Failed to upload file '".$file."' to storage: ". $e);
 51        } 
 52
 53        @fclose($handle);
 54        return true;
 55    } else {        
 56        error_log("Failed to open file '".$file."' to upload to storage.");
 57        return false;
 58    }
 59}
 60
 61## get cache time by mime type
 62function getCacheTimeByMimeType($mime)
 63{  
 64    $mime = strtolower($mime);
 65
 66    $types = array(
 67        "application/json" => 604800,// 7 days
 68        "application/javascript" => 604800,// 7 days
 69        "application/xml" => 604800,// 7 days
 70        "application/xhtml+xml" => 604800,// 7 days
 71        "image/bmp" => 604800,// 7 days
 72        "image/gif" => 604800,// 7 days
 73        "image/jpeg" => 604800,// 7 days
 74        "image/png" => 604800,// 7 days
 75        "image/tiff" => 604800,// 7 days
 76        "image/svg+xml" => 604800,// 7 days
 77        "image/x-icon" => 604800,// 7 days
 78        "text/plain" => 604800, // 7 days
 79        "text/html" => 604800,// 7 days
 80        "text/css" => 604800,// 7 days
 81        "text/richtext" => 604800,// 7 days
 82        "text/xml" => 604800,// 7 days
 83    );
 84
 85    // return value
 86    if(array_key_exists($mime, $types))
 87    {
 88        return $types[$mime];
 89    }
 90
 91    return FALSE;
 92}
 93
 94## removes file from the storage. Usage: storageAddFile("myContainer", "filename-on-storage.png")
 95function storageRemoveFile($containerName, $fileName)
 96{
 97    # Setup a specific instance of an Azure::Storage::Client
 98    $connectionString = "DefaultEndpointsProtocol=https;AccountName=".getenv('STORAGE_ACCOUNT_NAME').";AccountKey=".getenv('STORAGE_ACCOUNT_KEY');
 99    // Create blob client.
100    $blobClient = BlobRestProxy::createBlobService($connectionString);
101
102    try
103    {
104        $blobClient->deleteBlob($containerName, $fileName);
105    } catch ( Exception $e ) {
106        error_log("Failed to delete file '".$fileName."' from storage");
107    } 
108
109    return true;
110}
111?>

The source code does not win a beauty award, but unfortunately cannot be integrated into the existing solution in any other way. Nevertheless, this snippet shows how easy it is to put files into the Azure Storage - even with 20 years old legacy code.

This temporary and will soon be completely replaced by an ASP.NET Core solution.

Related articles

Automatic TTL in Azure Cosmos DB with .NET

Aug 17, 2026 - 17 min read

Automatic TTL in Azure Cosmos DB with .NET

Temporary data is easy to create and surprisingly difficult to remove reliably. Sessions, idempotency keys, import buffers, transient …

Run Hono on Azure Static Web Apps: managed Functions APIs for static frontends

Jul 19, 2026 - 8 min read

Run Hono on Azure Static Web Apps: managed Functions APIs for static frontends

Azure Static Web Apps is primarily a host for static frontend assets, but it can also deploy a small HTTP API alongside the frontend. That …

Run Hono on Azure: Container Apps, Functions, App Service and AKS compared

Jul 12, 2026 - 14 min read

Run Hono on Azure: Container Apps, Functions, App Service and AKS compared

Hono is often associated with Cloudflare Workers and for good reason. Its small routing model, Web Standard API surface and direct fetch …


BEN ABT

BEN ABT

Ben is Chief Engineering Officer and Principal Software Engineer at Medialesson.de, with a strong focus on .NET and Microsoft Azure. In his professional role, he designs and builds highly scalable platforms for hybrid and cloud-based scenarios. He also advises companies and C-levels on migrating to the sovereign cloud.

He runs myCSharp.de, the largest and most active German-speaking C# community forum, actively contributes to both his own and external open-source projects and regularly shares his knowledge through his blog, at community events, conferences and as a writer for technical magazines.

Let's Work Together

Looking for an experienced Platform Architect or Engineer for your next project? Whether it's cloud migration, platform modernization or building new solutions from scratch - I'm here to help you succeed.

New Platforms

Modernization

Training & Consulting

Contact Me
X Facebook LinkedIn WhatsApp
Back Next Blog Post

Open for work!

Contact Me
BEN ABT BEN ABT Software Engineer · Microsoft MVP Passionate about .NET, Azure, performance optimization and sustainable software engineering.

Medialesson GmbH Logo

Microsoft MVP Logo

Recent posts

View all
Stop Using nginx as Your Default Static File Server in Docker

Stop Using nginx as Your Default Static File Server in …

Oct 24, 2026
Containerizing .NET in 2026 Without a Dockerfile

Containerizing .NET in 2026 Without a Dockerfile

Oct 20, 2026
Problem Details in ASP.NET Core and .NET 11

Problem Details in ASP.NET Core and .NET 11

Oct 5, 2026
Resilience in .NET with Microsoft.Extensions.Resilience

Resilience in .NET with Microsoft.Extensions.Resilience

Sep 21, 2026
What Matters in ASP.NET Core 11

What Matters in ASP.NET Core 11

Sep 14, 2026

Tags

.NET (192) Csharp (96) ASP.NET Core (48) Azure (41) DevOps (17) Docker (14) Microsoft (14) EF Core (11) Microsoft MVP (11) AI (10) GitHub (10) GitHub Copilot (10) ASP.NET (9) Security (9) Synology (9) Architecture (8) Raspberry (8) Azure Functions (7) Cloudflare (7) Bicep (6)
benjamin-abt.com

About BEN

Benjamin Abt is a Software Engineer, Platform Architect and Microsoft MVP specializing in .NET, Azure, cloud architecture, performance optimization and sustainable software development.

Connect

  • Follow me on GitHub
  • Follow me on LinkedIn
  • Follow me on Mastodon
  • Microsoft MVP profile
  • Follow SchwabenCode on GitHub
  • Follow me on X

Quick Links

  • Portfolio
  • Blog
  • Workshops & Training
  • Publications
  • Get in Touch
  • Sitemap
Open for Work

© Copyright Benjamin Abt & SchwabenCode | 2011 - 2026

Content licensed under CC BY 4.0 unless otherwise noted.

  • Impressum
  • Privacy
  • Contact