Content Disposition Header

Apr 22, 2024

I have been working on a PDF download feature for BrewersInsight. We have created a PDF generation service that takes in data to generate a Bill of Ladding. The service first generates a PDF then stores it in a Azure Storage Account and create a URL to access it.

function generateSASUri(name: string) {
  const blockBlobClient: any = pdfStoreClient.getBlockBlobClient(name);

  // Define the permissions and expiration time for the SAS token
  const sasTokenExpires = new Date();
  sasTokenExpires.setMinutes(sasTokenExpires.getMinutes() + 60); // Set the expiration time (e.g., 1 hour from now)
  const permissions = new BlobSASPermissions();
  permissions.read = true; // Allow read access

  // Generate the SAS token
  const sasQueryParameters = generateBlobSASQueryParameters(
    {
      containerName: pdfStoreClient.containerName,
      blobName: name,
      startsOn: new Date(),
      expiresOn: sasTokenExpires,
      permissions,
      contentDisposition: "inline",
    },

    //@ts-ignore
    new StorageSharedKeyCredential(
      blobServiceClient.accountName,
      blobServiceClient.credential.accountKey,
    ),
  );

  // Combine the SAS token with the blob URL to create the complete URL
  const blobUrlWithSAS = `${blockBlobClient.url}?${sasQueryParameters}`;
  console.log(
    "🚀 ~ file: generatePdf.ts:406 ~ generateSASUri ~ blobUrlWithSAS:",
    blobUrlWithSAS,
  );

  return blobUrlWithSAS;
}

I had small headache figuring out why Chromium browsers were prompting the user to save the PDF when I had explicitly set the Content Disposition header to inline. What was most troubling was that I was not having this issue while using the Firefox browser.

The solution has to also set the Content Type header to application/pdf.

const sasQueryParameters = generateBlobSASQueryParameters(
  {
    containerName: pdfStoreClient.containerName,
    blobName: name,
    startsOn: new Date(),
    expiresOn: sasTokenExpires,
    permissions,
    contentDisposition: "inline",
    contentType: "application/pdf", // <==== HERE!
  },

  //@ts-ignore
  new StorageSharedKeyCredential(
    blobServiceClient.accountName,
    blobServiceClient.credential.accountKey,
  ),
);

After that everything started to work as expected!