简体   繁体   中英

Stream video from Azure Function in C#

I'm trying to write an Azure HttpTrigger Function that will stream a video from blob storage.

At the moment, I have the following code, but this does not stream.

    [FunctionName(nameof(GetVideo))]
    public async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "GET", Route = "Video/{videoID}")] HttpRequestMessage request,
        ExecutionContext executionContext,
        ILogger log,
        string videoID)
    {
        IActionResult result;

        string storageConnectionString = _configurationSettings.GetStringValue("StorageConnectionString");

        if (!await _blobStorage.BlobExists(storageConnectionString, "Videos", videoID).ConfigureAwait(false))
        {
            result = new NotFoundResult();
        }
        else
        {
            string videoMimeType = _configurationSettings.GetStringValue("VideoMimeType", DefaultVideoMimeType);

            Stream stream = await _blobStorage.GetBlobAsStream(storageConnectionString, "Videos", videoID).ConfigureAwait(false);
            byte[] videoBytes = GetBytesFromStream(stream);

            result = new FileContentResult(videoBytes, videoMimeType);
        }

        return result;
    }

Can anyone help?

What do you mean this does not stream , I tried to bind the input blob and return it, it succeeds. Maybe you could refer to my below code.

public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            [Blob("test/test.mp4", FileAccess.Read)] Stream myBlob,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");


            byte[] bytes = new byte[myBlob.Length];

            myBlob.Read(bytes, 0, bytes.Length);
            myBlob.Seek(0, SeekOrigin.Begin);

            var result = new FileContentResult(bytes, "video/mp4");
            return result;

        }

Update : Suppose you want to request the dynamic blob name in the HTTP request, you could refer to the below code, bind the container the get the blob and download it to bytes. I pass the blob name in the HTTP request query parameter.

public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            [Blob("test", FileAccess.Read,Connection = "AzureWebJobsStorage")] CloudBlobContainer myBlob,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");
            string filename = req.Query["filename"];
            CloudBlockBlob blob= myBlob.GetBlockBlobReference(filename);

            await blob.FetchAttributesAsync();

            long fileByteLength = blob.Properties.Length;
            byte[] fileContent = new byte[fileByteLength];
            for (int i = 0; i < fileByteLength; i++)
            {
                fileContent[i] = 0x20;
            }
            await blob.DownloadToByteArrayAsync(fileContent, 0);

            var result = new FileContentResult(fileContent, "video/mp4");
            return result;

        }

在此处输入图像描述

I did like below for minimum memory footprint (without keeping the full blob into bytes in memory). Note that instead of binding to stream, I am binding to a ICloudBlob instance (luckily, C# function supports several flavors of blob input binding ) and returning open stream. Tested it using memory profiler and works fine with no memory leak even for large blobs.

NOTE: You don't need to seek to stream position 0 or flush or dispose (disposing would be automatically done on response end);

using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Azure.Storage.Blob;

namespace TestFunction1
{
   public static class MyFunction
   {
        [FunctionName("MyFunction")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = "video/{fileName}")] HttpRequest req,
            [Blob("test/{fileName}", FileAccess.Read, Connection = "BlobConnection")] ICloudBlob blob,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            var blobStream = await blob.OpenReadAsync().ConfigureAwait(false);
            return new FileStreamResult(blobStream, "video/mp4");
        }
   }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM