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

时间:2018-08-15 22:34:34

标签: xamarin asp.net-core upload httpwebrequest azure-media-services

我正在尝试将从用户的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(); 

异常消息是“请求正文太大,超过了最大允许限制。” 状态码为“ RequestEntityTooLarge”。

如何上传大文件?这是HttpWebRequest还是Azure Media Services的问题?

1 个答案:

答案 0 :(得分:1)

如果您正在使用新的REST API版本,Azure Storage支持一个最大为256MB的shot upload(又名PutBlob API)。但是,由于您未指定REST API版本,因此默认情况下使用的是非常旧的版本,其中一次快照上传的最大支持大小为100MB。

使用x-ms-version: 2018-03-28标头可以在一个HTTP请求中上传多达256MB的内容。

如果必须处理较大的文件,则需要使用阻止并提交上传。您将需要使用PutBlock API从源文件暂存块。每个块最大可以为100MB。然后,您需要使用PutBlockList API提交所有块。如果您不必自己处理此逻辑,只需使用Azure Storage SDK for .NET(支持Xamarin)并使用uploadFromFile方法。它简单且具有弹性。