如何使用c#中的共享密钥(Rest Api)将文件上传到azure数据湖存储生成2? [英] How to Upload files to azure data lake storage generation 2 using shared key (Rest Api) in c#?
问题描述
<跨度风格= "颜色:#333333;字体家庭: '的Segoe UI', '很好的可读性',宋体,Arial字体,黑体,无衬线;字体大小:14px的">欲知道一种使用c#中的共享密钥(Rest API)在天蓝色数据湖存储生成2上传文件的方法。
我在上传文件时遇到问题。它给出了以下错误。
I am facing issue in uploading files. It gives below error.
下面是我的代码.File正在正确创建但是当我尝试在创建的文件中附加数据时它失败。如果我是,请帮助我 做错了。
Below is my code.File is getting created properly But it fails when i try to append data in created file.Please assist me if i am doing anything wrong.
&NBSP;
私有静态AuthenticationHeaderValue GetAuthorizationHeaderUpload(
&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;串storageAccountName,串storageAccountKey,日期时间现在,
&NBSP;&NBSP;&NBSP;&NBSP;&NBSP; httpRequestMessage httpRequestMessage,串ifMatch = QUOT;" ;,串MD5 = QUOT;")
&NBSP; &NBSP; &NBSP; &NBSP; {
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; AuthenticationHeaderValue authHV = null;
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP;试试
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; {
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; //这是邮件签名的原始表示。
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; HttpMethod方法= httpRequestMessage.Method;
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; String MessageSignature = String.Format(" {0} \\\
\\\
\ n {1} \\\
{5} \ n \ n \ n \\ n {2} \ n \ n \ n \\ n {3} {4} \ n {5} \ n {6}",&b $ b &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP; method.ToString(),
&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP; &NBSP;(方法== HttpMethod.Get ||方法== HttpMethod.Head ||方法== HttpMethod.Put ||方法== HttpMethod.Delete)的String.Empty
&NBSP;?&NBSP; &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;:httpRequestMessage.Content.Headers.ContentLength.ToString(),
&NBSP;&NBSP;&NBSP ;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP; ifMatch,
&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP ; GetCanonicalizedHeaders(httpRequestMessage),
& nbsp; GetCanonicalizedResource(httpRequestMessage.RequestUri,storageAccountName),
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; md5);
$
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; //现在把它变成一个字节数组。
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; byte [] SignatureBytes = Encoding.UTF8.GetBytes(MessageSignature);
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; //创建存储密钥的HMACSHA256版本。
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; HMACSHA256 SHA256 =新HMACSHA256(Convert.FromBase64String(storageAccountKey));
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; //计算SignatureBytes的哈希值并将其转换为base64字符串。
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; string signature = Convert.ToBase64String(SHA256.ComputeHash(SignatureBytes));
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; //这是将添加到请求标头列表的实际标头。
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; //你可以在这里停止代码并在返回之前查看'authHV'的值。
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; authHV =新AuthenticationHeaderValue(QUOT; SharedKey" ;,
&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP; storageAccountName + QUOT;:" + Convert.ToBase64String( SHA256.ComputeHash(SignatureBytes)));
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; }¥b $ b &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; catch(例外情况)
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; {
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; authHV = null;
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; }¥b $ b &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;返回authHV;
&NBSP; &NBSP; &NBSP; }
private static AuthenticationHeaderValue GetAuthorizationHeaderUpload(
string storageAccountName, string storageAccountKey, DateTime now,
HttpRequestMessage httpRequestMessage, string ifMatch = "", string md5 = "")
{
AuthenticationHeaderValue authHV = null;
try
{
// This is the raw representation of the message signature.
HttpMethod method = httpRequestMessage.Method;
String MessageSignature = String.Format("{0}\n\n\n{1}\n{5}\n\n\n\n{2}\n\n\n\n{3}{4}\n{5}\n{6}",
method.ToString(),
(method == HttpMethod.Get || method == HttpMethod.Head || method == HttpMethod.Put || method == HttpMethod.Delete) ? String.Empty
: httpRequestMessage.Content.Headers.ContentLength.ToString(),
ifMatch,
GetCanonicalizedHeaders(httpRequestMessage),
GetCanonicalizedResource(httpRequestMessage.RequestUri, storageAccountName),
md5);
// Now turn it into a byte array.
byte[] SignatureBytes = Encoding.UTF8.GetBytes(MessageSignature);
// Create the HMACSHA256 version of the storage key.
HMACSHA256 SHA256 = new HMACSHA256(Convert.FromBase64String(storageAccountKey));
// Compute the hash of the SignatureBytes and convert it to a base64 string.
string signature = Convert.ToBase64String(SHA256.ComputeHash(SignatureBytes));
// This is the actual header that will be added to the list of request headers.
// You can stop the code here and look at the value of 'authHV' before it is returned.
authHV = new AuthenticationHeaderValue("SharedKey",
storageAccountName + ":" + Convert.ToBase64String(SHA256.ComputeHash(SignatureBytes)));
}
catch (Exception ex)
{
authHV = null;
}
return authHV;
}
///< summary>
&NBSP; &NBSP; &NBSP; ///将以x-ms开头的标题放在列表中并对其进行排序。
&NBSP; &NBSP; &NBSP; ///然后将它们格式化为一串[key:value\]值连接成一个字符串。
&NBSP; &NBSP; &NBSP; ///(Canonicalized Headers =格式标准化的标题)。
&NBSP; &NBSP; &NBSP; ///< / summary>
&NBSP; &NBSP; &NBSP; ///< param name =" httpRequestMessage">将对存储服务发出的请求。< / param>
&NBSP; &NBSP; &NBSP; ///< returns>错误消息;如果没问题,请留空。< / returns>
&NBSP; &NBSP; &NBSP;私有静态字符串GetCanonicalizedHeaders(HttpRequestMessage httpRequestMessage)
&NBSP; &NBSP; &NBSP; {
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; var headers =来自httpRequestMessage.Headers中的kvp
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;其中kvp.Key.StartsWith(" x-ms-",StringComparison.OrdinalIgnoreCase)
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; orderby kvp.Key
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;选择新的{Key = kvp.Key.ToLowerInvariant(),kvp.Value};
$
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; StringBuilder sb = new StringBuilder();
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; //以正确的格式创建字符串;这就是使标题"标准化"的原因。 -
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; //&NBSP; 表示标准格式。 http://en.wikipedia.org/wiki/Canonicalization
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; foreach(标题中的var kvp)
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; {
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; StringBuilder headerBuilder = new StringBuilder(kvp.Key);
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; char separator =':';
$
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; //获取每个标题的值,如果找到则删除\\ n,然后用密钥附加它。
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; foreach(字符串headerValues in kvp.Value)
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; {
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; string trimmedValue = headerValues.TrimStart()。替换(" \\\\ n",String.Empty);
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; headerBuilder.Append(separator).Append(trimmedValue);
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; //将其设置为逗号;这只会被使用
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; //&NBSP; 如果其中一个标题有多个值。
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; separator =',';
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; }¥b $ b &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; sb.Append(headerBuilder.ToString())。追加(" \ n");
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; }¥b $ b &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; return sb.ToString();
&NBSP; &NBSP; &NBSP; }
/// <summary>
/// Put the headers that start with x-ms in a list and sort them.
/// Then format them into a string of [key:value\n] values concatenated into one string.
/// (Canonicalized Headers = headers where the format is standardized).
/// </summary>
/// <param name="httpRequestMessage">The request that will be made to the storage service.</param>
/// <returns>Error message; blank if okay.</returns>
private static string GetCanonicalizedHeaders(HttpRequestMessage httpRequestMessage)
{
var headers = from kvp in httpRequestMessage.Headers
where kvp.Key.StartsWith("x-ms-", StringComparison.OrdinalIgnoreCase)
orderby kvp.Key
select new { Key = kvp.Key.ToLowerInvariant(), kvp.Value };
StringBuilder sb = new StringBuilder();
// Create the string in the right format; this is what makes the headers "canonicalized" --
// it means put in a standard format. http://en.wikipedia.org/wiki/Canonicalization
foreach (var kvp in headers)
{
StringBuilder headerBuilder = new StringBuilder(kvp.Key);
char separator = ':';
// Get the value for each header, strip out \r\n if found, then append it with the key.
foreach (string headerValues in kvp.Value)
{
string trimmedValue = headerValues.TrimStart().Replace("\r\n", String.Empty);
headerBuilder.Append(separator).Append(trimmedValue);
// Set this to a comma; this will only be used
// if there are multiple values for one of the headers.
separator = ',';
}
sb.Append(headerBuilder.ToString()).Append("\n");
}
return sb.ToString();
}
///< summary>
&NBSP; &NBSP; &NBSP; ///签名字符串的这一部分代表存储帐户
&NBSP; &NBSP; &NBSP; ///&NBSP; 请求的目标。还将包含任何其他查询参数/值。
&NBSP; &NBSP; &NBSP; ///对于ListContainers,这将返回如下内容:
&NBSP; &NBSP; &NBSP; ///&NBSP; / storageaccountname / \ ncomp:list
&NBSP; &NBSP; &NBSP; ///< / summary>
&NBSP; &NBSP; &NBSP; ///< param name =" address">存储服务的URI。< / param>
&NBSP; &NBSP; &NBSP; ///< param name =" accountName">存储帐户名称。< / param>
&NBSP; &NBSP; &NBSP; ///< returns>表示规范化资源的字符串。< / returns>
&NBSP; &NBSP; &NBSP;私有静态字符串GetCanonicalizedResource(Uri地址,字符串storageAccountName)
&NBSP; &NBSP; &NBSP; {
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; //绝对路径是"/"因为我们收到了一个集装箱清单。
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; StringBuilder sb = new StringBuilder(" /")。Append(storageAccountName).Append(address.AbsolutePath);
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; // Address.Query是资源,例如"?comp = list"。
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; //这最终得到一个NameValueCollection,其中1个条目有key = comp,value = list。
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; //如果您有更多查询参数,它会有更多条目。
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; NameValueCollection values = ParseQueryString(address.Query);
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; foreach(值中的var项目.AllKeys.OrderBy(k => k))
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; {
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; values [item] = WebUtility.UrlDecode(values [item]);
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; if(!string.IsNullOrEmpty(item))
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; sb.Append('\ n')。追加(项目)。附加(':')。追加(值[item]);
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; }
&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; return sb.ToString();
&NBSP; &NBSP; &NBSP; }
/// <summary>
/// This part of the signature string represents the storage account
/// targeted by the request. Will also include any additional query parameters/values.
/// For ListContainers, this will return something like this:
/// /storageaccountname/\ncomp:list
/// </summary>
/// <param name="address">The URI of the storage service.</param>
/// <param name="accountName">The storage account name.</param>
/// <returns>String representing the canonicalized resource.</returns>
private static string GetCanonicalizedResource(Uri address, string storageAccountName)
{
// The absolute path is "/" because for we're getting a list of containers.
StringBuilder sb = new StringBuilder("/").Append(storageAccountName).Append(address.AbsolutePath);
// Address.Query is the resource, such as "?comp=list".
// This ends up with a NameValueCollection with 1 entry having key=comp, value=list.
// It will have more entries if you have more query parameters.
NameValueCollection values = ParseQueryString(address.Query);
foreach (var item in values.AllKeys.OrderBy(k => k))
{
values[item] = WebUtility.UrlDecode(values[item]);
if (!string.IsNullOrEmpty(item))
sb.Append('\n').Append(item).Append(':').Append(values[item]);
}
return sb.ToString();
}
推荐答案
请允许任何人帮助我。
这篇关于如何使用c#中的共享密钥(Rest Api)将文件上传到azure数据湖存储生成2?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!