在 Blob 上存储的媒体文件如何设置 Content-type?

101
我们有一个托管在Azure上的网站,是基于媒体的,并且我们正在使用JWPlayer进行HTTP伪流媒体播放。媒体文件以3种格式 - mp4,ogg,webm存储在blob中。
问题在于所有类型的媒体文件的内容类型都设置为application/octet-stream。由于这个原因,在媒体播放和进度条中存在一些问题。 如何设置存储在blob中的文件的适当Content-type(例如-video/mp4,video/ogg,video/webm)? 我不想通过进入blob界面为每个文件手动设置它。必须有其他方法可以做到这一点,但我还不知道。也许是一个配置文件,设置文件等等。或者也许是一个代码块来设置同一文件夹中所有文件的Content-type。 有什么建议吗?谢谢。
10个回答

137
这应该可以工作:
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();
}

或者设置一个字典,这样你就不必编写大量的if语句。


1
@smarx:在CDN中是否也可以做同样的事情?http://stackoverflow.com/questions/21847663/changing-video-content-type-mime-type-in-cdn-in-drupal-7 - Hitesh
1
有没有可能直接在Azure门户上设置,而不需要编码? - Emil
5
以下是一篇博客文章,其中包含了一份详尽的扩展名与MIME类型映射列表。https://ppolyzos.com/2015/10/27/apply-proper-content-type-to-files-in-azure-storage-containers-based-on-file-extensions/ - dragon788
2
值得一提的是,如果您可以访问System.Web和.NET 4.5或更高版本,则可以调用MimeMapping.GetMimeMapping("somefile.mp4")来获取内容类型。有关更多详细信息,请参见MSDN - David Yates

77

很不幸,这里接受的答案目前在最新的SDK(12.x.+)上已经无法使用。

使用最新的SDK时,内容类型应通过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可以是一个新的BinaryData(byte[])

2
它运行良好。在我看来,目前这个答案应该被标记为已接受。 - ElConrado
谢谢您。我在12.x文档中找不到这个内容。 - Hallmanac
对于任何正在寻找Golang解决方案的人来说,应该是这样的:HTTPHeaders: &blob.HTTPHeaders{ BlobContentType: &contentType },并且在指定上传选项时,某处应该有contentType := "application/pdf" - undefined

14

以下是将视频上传到Azure Blob Storage并设置正确的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;
}

7
使用 Azure.Storage.Blogs (12.8.4) ,可以设置文件的内容类型如下。 默认情况下,Azure 存储将文件存储为 application/octet-stream,如果是 *.svg 文件,则在 HTML 中无法正确呈现。 因此,在上传到 Blob 时,我们必须将 *.svg 文件保存在 azure blob 存储中,并使用内容类型 image/svg+xml。
以下是我可用的代码示例。
  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设置在标头上,应该放在blobClient.UploadAsync()的下面。


您的回答目前写得不够清晰,请[编辑]以添加更多细节,帮助其他人理解它如何解决所提出的问题。您可以在帮助中心中找到有关编写好答案的更多信息。 - Community

2

在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)

1
使用 Azure Storage v10 SDK,可以使用 BlockBlobURL 将 Blob 上传,如 Node.js 快速入门中所述
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);

上传后可以使用setHTTPHeaders方法设置内容类型:
// Set content type to text/plain
await blockBlobURL.setHTTPHeaders(aborter, { blobContentType: "text/plain" });

文件可以使用@azure/storage-blob中的uploadFileToBlockBlob方法上传。

0

这是我所做的

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
如果您的API用于上传文件,则可以执行以下操作。
使用Azure.Storage.Files.Datalake v12.12.1和Datalake存储Gen v2,您可以使用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;
}

关于内容类型和我正在使用的GetMimeType方法,可以在这里了解更多。


0
使用PHP,可以通过设置内容类型来上传视频。
$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 />";
}

1
目前而言,此功能与当前的软件包不兼容。 - Carey Richardson

-1
您可以使用Azure存储资源管理器手动完成此操作。右键单击要更改的文件,选择属性。转到ContentType并编辑值以更正为正确的值,例如“video\mp4”。

2
你能否编辑这篇帖子,让它更加有力?请注意,问题中说“我不想通过进入 blob 接口手动处理每个文件”。 - Scratte

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接