Azure Blob Storage – Image Download & Display Issues in Drupal 10 (Fixes and Hook for URL Handling)

Created on 1 May 2025, 4 months ago

Problem/Motivation

In Drupal 10, when using the az_blob_fs module to store images in Azure Blob Storage, images can be uploaded successfully but cannot be downloaded or displayed properly.

Steps to reproduce

Steps to reproduce

  1. Install and configure the az_blob_fs module in a Drupal 10 site.
  2. Configure a media/image field to use the Azure Blob filesystem as its storage backend.
  3. Upload an image using the media field.
  4. Observe that the image is uploaded successfully to Azure Blob Storage.
  5. Try to view the image on the frontend (e.g., via image field, media, or image style).
  6. The image does not render. On trying to directly access the image URL, the following error is displayed:
    <Code>PublicAccessNotPermitted</Code>
    <Message>Public access is not permitted on this storage account.</Message>

Proposed resolution

Two changes are proposed to address this:

  1. Image URL Rewriting: Implement hook_file_url_alter() in a custom module to rewrite Azure Blob Storage URLs to a relative path that Drupal can process correctly. This is needed when Azure Blob public access is disabled:
    function YOUR_MODULE_file_url_alter(&$uri) {
      // Replace with your actual Azure container base URL.
      $azure_base_url = 'https://<your-storage-account>.blob.core.windows.net/<your-container&gt>/';
      
      // Dynamically get the site's base URL.
      $base_url = \Drupal::request()->getSchemeAndHttpHost();
      
      // Define the internal path prefix for image style downloads.
      $replacement_path = $base_url . '/azblob/files/';
      
      // If the URI starts with the Azure base URL, replace it.
      if (strpos($uri, $azure_base_url) === 0) {
        $uri = str_replace($azure_base_url, $replacement_path, $uri);
      }
    }

    Replace <your-storage-account> and <your-container> with your own Azure values. This hook ensures that image URLs are routed through Drupal so they can be processed by the download controller even when public blob access is disabled.

  2. Image Download Fix (Dynamic Configuration): Update AzBlobFsImageStyleDownloadController.php to retrieve the Azure connection string and container name from the module configuration instead of hardcoding them. This allows flexibility across environments:
    use MicrosoftAzure\Storage\Blob\BlobRestProxy;
    use Symfony\Component\HttpFoundation\BinaryFileResponse;
    use MicrosoftAzure\Storage\Common\Exceptions\ServiceException;
    
    $config = \Drupal::config('az_blob_fs.settings');
    $connectionString = $config->get('az_blob_connection_string');
    $containerName = $config->get('az_blob_container_name');
    
    try {
      // Create Blob Client
      $blobClient = BlobRestProxy::createBlobService($connectionString);
    
      // Get blob content from Azure Blob Storage
      $blob = $blobClient->getBlob($containerName, $imagePath);
    
      // Save blob stream to a temporary file
      $tmpFile = sys_get_temp_dir() . '/' . mb_strtolower(uniqid('azblob_', true) . '_' . basename($imagePath));
      file_put_contents($tmpFile, stream_get_contents($blob->getContentStream()));
    
      // Create and return image response
      $response = new BinaryFileResponse($tmpFile);
      $response->headers->set('Content-Type', mime_content_type($tmpFile));
      $response->headers->set('Content-Disposition', 'inline; filename="' . basename($imagePath) . '"');
      $response->send();
    } catch (ServiceException $e) {
      echo "Error: " . $e->getMessage();
      http_response_code(500); // Internal Server Error
    }

    This change ensures that the download logic is environment-agnostic and easier to manage via the Drupal admin config UI or settings.php overrides.

Remaining tasks

  • Refactor the controller to use configuration for storage settings instead of hardcoding (completed).
  • Add a configuration form field for the Azure Blob connection string. This allows site administrators to input the connection string via the UI, which is then used for secure image retrieval from Azure Blob Storage.

User interface changes

  • A new text field labeled "Connection String" has been added to the Azure Blob Storage settings form.
  • This allows administrators to input the full Azure Blob Storage connection string directly through the Drupal admin UI.

API changes

None.

Data model changes

None.

Feature request
Status

Active

Version

2.0

Component

Code

Created by

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Production build 0.71.5 2024