azure 上传blob到ams(CreateFromBlob)
遇到的错误:The destination storage credentials must contain the account key credentials,参数名: destinationStorageCredentials
解决方法:AccountName与AccountKey参数值错误
AccountName就是存储账户名字
AccountKey值获取方式:打开存储账户-->访问秘钥-->key1或者key2
Azure上传资产SDK
public class AzureMediaServiceController : ApiController { // Read values from the App.config file. private static readonly string _AADTenantDomain = ConfigurationManager.AppSettings["AMSAADTenantDomain"]; private static readonly string _RESTAPIEndpoint = ConfigurationManager.AppSettings["AMSRESTAPIEndpoint"]; private static readonly string _AMSClientId = ConfigurationManager.AppSettings["AMSClientId"]; private static readonly string _AMSClientSecret = ConfigurationManager.AppSettings["AMSClientSecret"]; private static CloudMediaContext _context = null; [HttpPost, Route("api/AzureMediaService/DeliverVideo")] // GET: AMSDeliverVideo public string DeliverVideo(string fileName) { GetCloudMediaContext(); IAsset inputAsset = UploadFile(fileName, AssetCreationOptions.None); var strsasUri = PublishAssetGetURLs(inputAsset); return strsasUri; } /// <summary> /// 获取媒体文件上下文 /// </summary> private void GetCloudMediaContext() { AzureAdTokenCredentials tokenCredentials = new AzureAdTokenCredentials(_AADTenantDomain, new AzureAdClientSymmetricKey(_AMSClientId, _AMSClientSecret), AzureEnvironments.AzureCloudEnvironment); var tokenProvider = new AzureAdTokenProvider(tokenCredentials); _context = new CloudMediaContext(new Uri(_RESTAPIEndpoint), tokenProvider); } /// <summary> /// 创建新资产并上传视频文件 /// </summary> /// <param name="fileName">上传文件名称,如:F:\BigBuck.mp4</param> static public IAsset UploadFile(string fileName, AssetCreationOptions options) { IAsset inputAsset = _context.Assets.CreateFromFile( fileName, options, (af, p) => { Console.WriteLine("Uploading '{0}' - Progress: {1:0.##}%", af.Name, p.Progress); }); return inputAsset; } static public string PublishAssetGetURLs(IAsset asset) { // Publish the output asset by creating an Origin locator for adaptive streaming, // and a SAS locator for progressive download. //用于流媒体(例如 MPEG DASH、HLS 或平滑流式处理)的 OnDemandOrigin 定位符 //_context.Locators.Create( // LocatorType.OnDemandOrigin, // asset, // AccessPermissions.Read, // TimeSpan.FromDays(30)); //用于下载媒体文件的访问签名 _context.Locators.Create( LocatorType.Sas, asset, AccessPermissions.Read, TimeSpan.FromDays(30)); IEnumerable<IAssetFile> mp4AssetFiles = asset .AssetFiles .ToList() .Where(af => af.Name.EndsWith(".mp4", StringComparison.OrdinalIgnoreCase)); // Get the URls for progressive download for each MP4 file that was generated as a result // of encoding. //List<Uri> mp4ProgressiveDownloadUris = mp4AssetFiles.Select(af => af.GetSasUri()).ToList(); string mp4ProgressiveDownloadUris = mp4AssetFiles.Select(af => af.GetSasUri()).FirstOrDefault().OriginalString; return mp4ProgressiveDownloadUris; // Display the URLs for progressive download. // mp4ProgressiveDownloadUris.ForEach(uri => Console.WriteLine(uri + "\n")); } string storageConnectionString = ConfigurationManager.AppSettings["StorageConnectionString"]; string accountName = ConfigurationManager.AppSettings["AccountName"]; string accountKey = ConfigurationManager.AppSettings["AccountKey"]; /// <summary> /// 上传blob文件到ams中 /// </summary> /// <param name="fileName">文件名</param> public string UploadBlobFile(string fileName) { if (string.IsNullOrEmpty(fileName)) return string.Empty; CloudStorageAccount storageAccount = null; CloudBlobContainer cloudBlobContainer = null; if (CloudStorageAccount.TryParse(storageConnectionString, out storageAccount)) { try { // 创建CloudBlobClient,它代表存储帐户的Blob存储端点。 CloudBlobClient cloudBlobClient = storageAccount.CreateCloudBlobClient(); //fileName = "https://qdlsstorage.blob.core.windows.net/video/20190514165259-魔术视频.mp4"; //通过连接获取容器名字和文件名字 var index = fileName.IndexOf(accountName, StringComparison.CurrentCultureIgnoreCase); var temp = fileName.Substring(index + 1); var fs = temp.Split('/'); var containerName = fs[1]; fileName = fs[2]; 这一段代码根据你们自己的情况进行修改,我这个是因为传递的全路径才这么写的 // 获取Blob容器 cloudBlobContainer = cloudBlobClient.GetContainerReference(containerName); GetCloudMediaContext(); var storageCredentials = new StorageCredentials(accountName, accountKey); var cloudBlockBlob = cloudBlobContainer.GetBlockBlobReference(fileName); cloudBlockBlob.FetchAttributes();//这一句是关键,如果不加这一句就会报错,我把报错信息放到下面 var inputAsset = _context.Assets.CreateFromBlob(cloudBlockBlob, storageCredentials, AssetCreationOptions.None); var strsasUri = PublishAssetGetURLs(inputAsset); return strsasUri; } catch (Exception e) { Console.WriteLine(e); } } return null; } }
报错信息:
<?xml version="1.0" encoding="utf-8"?><m:error xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"><m:code /><m:message xml:lang="en-US">AssetFile ContentFileSize must not be negative</m:message></m:error>
参考地址:https://github.com/Azure/azure-sdk-for-media-services-extensions/issues/40 (这是通过谷歌找到的资料,百度根本不行)
直接上传文件到资产中调用方法:
var virtualPath = "/UploadFile/Files/"; var path = HttpContext.Current.Server.MapPath(virtualPath); if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } var fileFullPath = $"{path}{fileName}"; try { file.SaveAs(fileFullPath); var ams = new AzureMediaServiceController(); url = ams.DeliverVideo(fileFullPath); result = true; msg = $@"上传视频成功"; File.Delete(fileFullPath); } catch (Exception ex) { msg = "上传文件写入失败:" + ex.InnerException + ex.Message + ex.InnerException?.InnerException + "fileFullPath=" + fileFullPath; }
因为使用的是HTML自带的file上传控件,传递给接口的文件地址全路径是错误的,所以只能保存到接口服务器本地,上传到azure上去之后再删除这个文件。
上传blob到ams
var ams = new AzureMediaServiceController(); var t = ams.UploadBlobFile(fileUrl);