问题描述
我正在尝试使用REST API将文件上传到Azure存储容器中,而不使用任何SDK。
不使用Azure.Storage.Blobs SDK的原因是,它依赖于.netstandard2.0,并且在项目运行.NET Framework 4.6.1时,SDK引用的某些DLL不兼容。我在配置中尝试了程序集绑定重定向,但没有很好地进行锻炼(System.ValueTuple.dll参考问题)。
因此,我试图使用C#和REST API在没有SDK的情况下重新编写我的上载代码。
这是我正在尝试的代码
public class AzureRestApi
{
private string _x_ms_client_request_id = string.Empty;
private string _x_ms_date = string.Empty;
public string AzureStorageAccountName { get; set; }
public string AzureStorageAccessKey { get; set; }
public string BlobSaveFolder
{
get; set;
}
public string X_MS_DATE
{
get
{
return _x_ms_date;
}
}
public string X_MS_VERSION
{
get
{
return "2019-12-12";
}
}
public string BaseURI
{
get
{
return string.Format("https://{0}.blob.core.windows.net/",AzureStorageAccountName);
}
}
public AzureRestApi()
{
//Date and GUID should be same that is used to create the key signing string and the one that is being sent in the
//header of REST api requests.
_x_ms_date = DateTime.UtcNow.ToString("R",CultureInfo.InvariantCulture);
_x_ms_client_request_id = System.Guid.NewGuid().ToString();
}
public bool UploadBlobToContainer(string filePath,string containerName)
{
bool isuploaded = false;
try
{
FileInfo fileInfo = new FileInfo(filePath);
long contentLength = fileInfo.Length;
long range = contentLength - 1;
string method = "PUT";
string contentType = "application/pdf";
string blobName = fileInfo.Name;
string blobURI = BaseURI + containerName + "/" + blobName;
string xmsHeader = $"x-ms-blob-type:BlockBlob\nx-ms-date:{X_MS_DATE};\nx-ms-version:{X_MS_VERSION}";
string resHeader = $"/{AzureStorageAccountName}/{containerName}/{blobName}";
if (WebRequest.Create(blobURI) is HttpWebRequest request)
{
request.Method = method;
request.ContentType = contentType;
request.ContentLength = contentLength;
request.Headers.Add("x-ms-blob-type","BlockBlob");
request.Headers.Add("x-ms-date",X_MS_DATE);
request.Headers.Add("x-ms-version",X_MS_VERSION);
request.Headers.Add("Authorization",GetAuthorizationHeader(method,xmsHeader,resHeader,request));
using (Stream requestStream = request.GetRequestStream())
{
byte[] fileContents = null;
using (FileStream fs = fileInfo.OpenRead())
{
fileContents = new byte[fs.Length];
fs.Read(fileContents,fileContents.Length);
fs.Close();
}
requestStream.Write(fileContents,fileContents.Length);
}
if (request.GetResponse() is HttpWebResponse response)
{
if (response.StatusCode == HttpStatusCode.OK)
isuploaded = true;
else
isuploaded = false;
}
}
}
catch (Exception ex)
{
Log.LogException(ex);
}
return isuploaded;
}
private string GetAuthorizationHeader(string method,string xmsHeader,string resHeader,HttpWebRequest request)
{
string strToSign = $"{method}\n\n\n{request.ContentLength}\n\n{request.ContentType}\n\n\n\n\n\n\n{xmsHeader}\n{resHeader}";
string signatureString = GetHashedString(strToSign,AzureStorageAccessKey);
string authorizationHeader = string.Format(
CultureInfo.InvariantCulture,"{0} {1}:{2}","SharedKey",AzureStorageAccountName,signatureString);
return authorizationHeader;
}
}
string storageName = "MyDefaultStorage";
string containerName = "MyDefaultContainer";
AzureRestApi restApi = new AzureRestApi()
{
AzureStorageAccountName = storageName,AzureStorageAccessKey = "MY_STORAGE_ACCOUNT_ACCESS_KEY",};
restApi.UploadBlobToContainer("E:\\UploadFiles\\UploadDocument1.pdf",containerName);
执行此行时抛出异常
if (request.GetResponse() is HttpWebResponse response)
我尝试使用PostMan模拟此请求,并收到此错误消息
Server Failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
The MAC signature found in the HTTP request 'RW1ACnL1aYqtSnJeHhV2694Ek95Olnf+V3Eup4Jt5ng=' is not the same as any computed signature. Server used following string to sign: 'PUT
461804
application/pdf
x-ms-blob-type:BlockBlob
x-ms-date:Wed,12 Aug 2020 19:30:20 GMT
x-ms-version:2019-12-12
/MyDefaultStorage/MyDefaultContainer/UploadDocument1.pdf'
我尝试了这些链接中给出的答案,如果该文件是文本文件,则可以使用,但是尝试使用pdf时失败
Azure rest api put blob REST Api to Azure blob storage using Access key
任何帮助将不胜感激。
谢谢 拉古纳森S
解决方法
您在此代码中添加了一个额外的分号:
string xmsHeader = $"x-ms-blob-type:BlockBlob\nx-ms-date:{X_MS_DATE};\nx-ms-version:{X_MS_VERSION}";
请更改为此:
string xmsHeader = $"x-ms-blob-type:BlockBlob\nx-ms-date:{X_MS_DATE}\nx-ms-version:{X_MS_VERSION}";
希望这可以为您提供帮助。