在 Xamarin 中将大文件上传到 Azure 媒体服务

Upload large files to Azure Media Services in Xamarin

我正在尝试将从用户的 iOS 或 Android 设备中选择的 .mp4 文件上传到我的 Azure 媒体服务帐户。

此代码适用于小文件(小于 ~95MB):

public static async Task<string> UploadBlob(string blobContainerSasUri, string blobName, byte[] blobContent, string path)
    {
        string responseString;
        int contentLength = blobContent.Length;
        string queryString = (new Uri(blobContainerSasUri)).Query;
        string blobContainerUri = blobContainerSasUri.Split('?')[0];
        string requestUri = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}/{1}{2}", blobContainerUri, blobName, queryString);

        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUri);
        request.Method = "PUT";
        request.AllowWriteStreamBuffering = false;
        request.Headers.Add("x-ms-blob-type", "BlockBlob");
        request.ContentLength = contentLength;
        request.Timeout = Int32.MaxValue;
        request.KeepAlive = true;

        int bufferLength = 1048576; //upload 1MB at time, useful for a simple progress bar.

        Stream requestStream = request.GetRequestStream();
        requestStream.WriteTimeout = Int32.MaxValue;

        ProgressViewModel progressViewModel = App.Locator.GetProgressBar(App.Locator.MainViewModel.currentModuleItemId);
        MyVideosPage myVideosPage = App.Locator.GetVideosPage(App.Locator.MainViewModel.currentModuleItemId);

        FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read);
        int nRead = 0;
        int currentPos = 0;
        while ((nRead = fileStream.Read(blobContent, currentPos, bufferLength)) > 0)
        {

            await requestStream.WriteAsync(blobContent, currentPos, nRead);
            currentPos += nRead;

        }
        fileStream.Close();
        requestStream.Close();

        HttpWebResponse objHttpWebResponse = null;
        try
        {
            // this is where it fails for large files
            objHttpWebResponse = (HttpWebResponse)request.GetResponse();

            Stream responseStream = objHttpWebResponse.GetResponseStream();
            StreamReader stream = new StreamReader(responseStream);

            responseString = stream.ReadToEnd();                       
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            if (objHttpWebResponse != null)
                objHttpWebResponse.Close();
        }
        return responseString;
    }

调用此行后抛出异常:

(HttpWebResponse)request.GetResponse(); 

异常消息是"The request body is too large and exceeds the maximum permissible limit." 异常 StatusCode 为 "RequestEntityTooLarge".

如何上传大文件?这是 HttpWebRequest 或 Azure 媒体服务的问题吗?

A​​zure 存储支持一个 shot upload(又名 PutBlob API),如果您使用的是新的 REST API 版本,则最多支持 256MB。但是由于您没有指定 REST API 版本,您默认使用一个非常旧的版本,其中一次上传的最大支持大小为 100MB。

使用 x-ms-version: 2018-03-28 header 可以在一个 HTTP 请求中上传最多 256MB。

如果您必须处理更大的文件,您将需要使用 block & commit 上传。您将需要使用 PutBlock API to stage blocks from the source file. Blocks can be up to 100MB each. Then you need to commit all the blocks using the PutBlockList API. If you don't have to deal with this logic yourself, simply use the Azure Storage SDK for .NET(支持 Xamarin)并使用 uploadFromFile 方法。它简单且有弹性。