99

We have a website hosted on Azure. It is media based, and we are using JWPlayer to playback media with HTTP pseudostreaming. The media files are stored on blob in 3 formats - mp4, ogg, webm.

The issue is the content type of media files is set as application/octet-stream for all types. Due to this there are some issues in media playback and progress bar.

How can I set the appropriate Content-type of files stored on blob (like - video/mp4, video/ogg, video/webm)?

I do not want to do it manually for each file by going in blob interface. There must be some other way to do it which I am not aware of. Perhaps a config file, settings file, etc sorts. Or perhaps a code block to set up the Content-type for all files stored in a folder.

Any suggestions? Thanks

Ian Kemp
  • 28,293
  • 19
  • 112
  • 138
Rahul Patwa
  • 2,319
  • 4
  • 18
  • 17

10 Answers10

137

This should work:

var storageAccount = CloudStorageAccount.Parse("YOURCONNECTIONSTRING");
var blobClient = storageAccount.CreateCloudBlobClient();

var blobs = blobClient
    .GetContainerReference("thecontainer")
    .ListBlobs(useFlatBlobListing: true)
    .OfType<CloudBlockBlob>();

foreach (var blob in blobs)
{
    if (Path.GetExtension(blob.Uri.AbsoluteUri) == ".mp4")
    {
        blob.Properties.ContentType = "video/mp4";
    }
    // repeat ad nauseam
    blob.SetProperties();
}

Or set up a dictionary so you don't have to write a bunch of if statements.

Dai
  • 141,631
  • 28
  • 261
  • 374
user94559
  • 59,196
  • 6
  • 103
  • 103
  • 1
    @smarx : Is it also possible to do the same thing in CDN, http://stackoverflow.com/questions/21847663/changing-video-content-type-mime-type-in-cdn-in-drupal-7 – Hitesh Feb 19 '14 at 10:11
  • 1
    Isn't there any possibility to set this up on Azure Portal directly? without coding – Emil Oct 19 '16 at 15:54
  • 5
    Here is a blog post with a comprehensive list of extension to mimetype mappings. https://ppolyzos.com/2015/10/27/apply-proper-content-type-to-files-in-azure-storage-containers-based-on-file-extensions/ – dragon788 May 01 '17 at 18:08
  • 2
    It might be worth mentioning that if you have access to System.Web and .NET 4.5 or higher, you can call MimeMapping.GetMimeMapping("somefile.mp4") to get the content type. See [MSDN](https://learn.microsoft.com/en-us/dotnet/api/system.web.mimemapping.getmimemapping?view=netframework-4.7.2) for more details. – David Yates Dec 03 '18 at 21:31
72

Unfortunately, the accepted answer here is not currently working for the latest SDK (12.x.+)

With the latest SDK, the content type should be set via BlobHttpHeaders.

var blobServiceClient = new BlobServiceClient("YOURCONNECTIONSTRING");
var containerClient = blobServiceClient.GetBlobContainerClient("YOURCONTAINERNAME");
var blob = containerClient.GetBlobClient("YOURFILE.jpg");

var blobHttpHeader = new BlobHttpHeaders { ContentType = "image/jpeg" };
 
var uploadedBlob = await blob.UploadAsync(YOURSTREAM, new BlobUploadOptions { HttpHeaders = blobHttpHeader });

YOURSTREAM could be a new BinaryData(byte[])

Softlion
  • 12,281
  • 11
  • 58
  • 88
Mehmet Taha Meral
  • 3,315
  • 28
  • 30
14

This is work example to upload video to Azure Blob Storage with right Content-Type:

public static String uploadFile(
     CloudBlobContainer container,String blobname, String fpath) {

    CloudBlockBlob blob;
    try {
        blob = container.getBlockBlobReference(blobname);
        File source = new File(fpath);

        if (blobname.endsWith(".mp4")) {
            System.out.println("Set content-type: video/mp4");
            blob.getProperties().setContentType("video/mp4");
        }

        blob.upload(new FileInputStream(source), source.length());

        return blob.getUri().toString();
    } catch (URISyntaxException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (StorageException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return null;
}
Vadym Dobroskok
  • 177
  • 1
  • 7
7

With Azure.Storage.Blogs (12.8.4), We can set content type of file as below. In Default, Azure Storage stores file in application/octet-stream, In case of *.svg file, doesn't properly render in html. So we have to save *.svg file in azure blob storage with content type image/svg+xml while uploading into blob.

Below is the code sample I got working.

  BlobServiceClient blobServiceClient = new BlobServiceClient("CONNECTIONSTRING");
  BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient("CONTAINERNAME");
  BlobClient blobClient = containerClient.GetBlobClient("BLOBNAME");
  try
  {

    Stream stream = file.OpenReadStream();
    await blobClient.UploadAsync(stream, true);
    blobClient.SetHttpHeaders(new BlobHttpHeaders() { ContentType = file.ContentType });
  }

ContentType Set on header should place just below the blobClient.UploadAsync().

Amrit Pariyar
  • 101
  • 2
  • 10
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jun 01 '22 at 07:41
1

With Azure Storage v10 SDK, blobs can be uploaded using BlockBlobURL as instructed in the Node.js quickstart:

const {
  Aborter,
  BlockBlobURL,
  ContainerURL,
  ServiceURL,
  SharedKeyCredential,
  StorageURL,
  uploadFileToBlockBlob
} = require("@azure/storage-blob");

const containerName = "demo";
const blobName = "quickstart.txt";
const content = "hello!";

const credentials = new SharedKeyCredential(
  STORAGE_ACCOUNT_NAME,
  ACCOUNT_ACCESS_KEY
);
const pipeline = StorageURL.newPipeline(credentials);
const serviceURL = new ServiceURL(
  `https://${STORAGE_ACCOUNT_NAME}.blob.core.windows.net`,
  pipeline
);

const containerURL = ContainerURL.fromServiceURL(serviceURL, containerName);
const blockBlobURL = BlockBlobURL.fromContainerURL(containerURL, blobName);

const aborter = Aborter.timeout(30 * ONE_MINUTE);
await blockBlobURL.upload(aborter, content, content.length);

Then content type can be set after the upload with the setHTTPHeaders method:

// Set content type to text/plain
await blockBlobURL.setHTTPHeaders(aborter, { blobContentType: "text/plain" });

Files can be uploaded with the uploadFileToBlockBlob method from @azure/storage-blob.

saaskis
  • 191
  • 3
  • 9
1

In python

azure_connection_str = libc.retrieve.get_any_secret('AZURE_STORAGE_CONNECTION')
blob_service_client = BlobServiceClient.from_connection_string(azure_connection_str)
blobs = blob_service_client.list_blobs()
my_content_settings = ContentSettings(content_type='video/mp4')

for blob in blobs:
    blob_client = blob_service_client.container_client.get_blob_client(blob)
    blob_client.set_http_headers(content_settings=my_content_settings)
Brando
  • 91
  • 1
  • 2
0

Using php, one can upload the video by setting the content type as follows

$blobRestProxy = ServicesBuilder::getInstance()->createBlobService($connectionString);
//upload
$blob_name = "video.mp4";
$content = fopen("video.mp4", "r");

$options = new CreateBlobOptions();
$options->setBlobContentType("video/mp4");
try {
    //Upload blob
    $blobRestProxy->createBlockBlob("containername", $blob_name, $content, $options);
    echo "success";
} catch(ServiceException $e){
    $code = $e->getCode();
    $error_message = $e->getMessage();
    echo $code.": ".$error_message."<br />";
}
Neeraj Dangol
  • 223
  • 1
  • 12
0

here is what i do

BlobHTTPHeaders h = new BlobHTTPHeaders();
String blobContentType = "image/jpeg";
h.withBlobContentType(blobContentType);
blobURL.upload(Flowable.just(ByteBuffer.wrap(Files.readAllBytes(img.toPath()))), img.length(), h, null, null, null)
.subscribe(resp-> {
  System.out.println("Completed upload request.");
  System.out.println(resp.statusCode());
});
0

If you are having API in the middle which is used to upload files you can do something like this.

Using Azure.Storage.Files.Datalake v12.12.1 and Datalake storage Gen v2 you can specify content type using DataLakeFileUploadOptions.

using Azure.Storage.Files
using Microsoft.AspNetCore.StaticFiles;
(...)

public async Task<IActionResult> UploadAsync(string container, string uploadDirectoryPath, 
         IFormFile file) {
     var dataLakeServiceClient = new DataLakeServiceClient(connString);
     var dataLakeFileSystemClient = dataLakeServiceClient.GetFileSystemClient(container);
     var dataLakeFileClient = dataLakeFileSystemClient
                             .GetFileClient(Path.Combine(uploadDirectoryPath, file.FileName));
 
     var fileStream = file.OpenReadStream();
     var mimeType = GetMimeType(file.FileName);
     var uploadOptions = new DataLakeFileUploadOptions()
     {
         HttpHeaders = new PathHttpHeaders() { ContentType = mimeType }                
     };

     await dataLakeFileClient.UploadAsync(fileStream, uploadOptions);
     return Ok();
}

private string GetMimeType(string fileName)
{
    var provider = new FileExtensionContentTypeProvider();
    if (!provider.TryGetContentType(fileName, out var contentType))
    {
        contentType = "application/octet-stream";
    }
    return contentType;
}

More about content types and GetMimeType method that I am using here.

Dušan
  • 269
  • 1
  • 11
-1

You can use Azure Storage Explorer to do this manually. Right-click the file to change and select Properties. Go to ContentType and edit the value to the correct one i.e. "video\mp4"

Dharman
  • 30,962
  • 25
  • 85
  • 135
Miguel
  • 1
  • 2
    Can you edit this post to make it more assertive? Note that the Question says "I do not want to do it manually for each file by going in blob interface" – Scratte Oct 09 '21 at 08:51