मैं Azure बाकी एपीआई के साथ एक बूँद डालने की कोशिश कर रहा हूँ। मैंने सफलतापूर्वक "GET" अनुरोध किया लेकिन मुझे "PUT" अनुरोध के साथ समस्या थी। जब मैं "पुट" अनुरोध करने का प्रयास करता हूं तो मुझे 404 त्रुटि मिलती है (मैंने स्टैक ओवरफ्लो में एक ही पोस्ट देखी है लेकिन इससे मेरी मदद नहीं हुई है)। मुझे यकीन नहीं है कि मैं जिस संदेश हस्ताक्षर का उपयोग करता हूं वह सही है (मैंने संदेश हस्ताक्षर की कोशिश की है लेकिन काम नहीं किया है)। कोई सुझाव?

public void UploadBlobWithRestAPI(string uri,  DateTime now)
{
    string blobName = "test.txt";
    string method = "PUT";
    string sampleContent = "This is sample text.";
    int contentLength = Encoding.UTF8.GetByteCount(sampleContent);
    string queryString = (new Uri(uri)).Query;
    string blobContainerUri = uri.Substring(0, uri.Length - queryString.Length);
    string requestUri = string.Format(CultureInfo.InvariantCulture, "{0}/{1}{2}", blobContainerUri, blobName, queryString);
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUri);
    string nnow = now.ToString("R", System.Globalization.CultureInfo.InvariantCulture);

    request.Method = method;
    request.Headers.Add("x-ms-version", "2015-02-21");
    request.Headers.Add("x-ms-date", nnow);
    request.ContentType = "text/plain; charset=UTF-8";
    request.Headers.Add("x-ms-blob-type", "BlockBlob");
    request.ContentLength = contentLength;

    using (Stream requestStream = request.GetRequestStream())
    {
        requestStream.Write(Encoding.UTF8.GetBytes(sampleContent), 0, contentLength);
    }

    request.Headers.Add("Authorization", AuthorizationHeader(method, now, request, "", ""));

    using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse())
    {
        MessageBox.Show(resp.StatusCode.ToString());
    }
}


public string AuthorizationHeader(string method, DateTime now, HttpWebRequest request,
        string ifMatch = "", string md5 = "")
{
    string MessageSignature;
    string StorageKey = "xxx";
    string StorageAccount = "upgradedevstorage";

    MessageSignature = String.Format("{0}\n\n\n{1}\n{5}\n\n\n\n{2}\n\n\n\n{3}{4}",
        method,
        (method == "GET" || method == "HEAD") ? String.Empty : request.ContentLength.ToString(),
        ifMatch,
        GetCanonicalizedHeaders(request),
        GetCanonicalizedResource(request.RequestUri, StorageAccount),
        md5
        );

 ???   //string MessageSignaturePut= String.Format("{0}\n\n{1}\n\n{2}{3}",
    //    method,
    //    "text/plain; charset=UTF-8",
    //    GetCanonicalizedHeaders(request),
    //    GetCanonicalizedResource(request.RequestUri, StorageAccount)
    //    );

    byte[] SignatureBytes = System.Text.Encoding.UTF8.GetBytes(MessageSignature);

    System.Security.Cryptography.HMACSHA256 SHA256 =
        new System.Security.Cryptography.HMACSHA256(Convert.FromBase64String(StorageKey));

    string signature = Convert.ToBase64String(SHA256.ComputeHash(SignatureBytes));

    string AuthorizationHeader = "SharedKey " + StorageAccount
        + ":" + Convert.ToBase64String(SHA256.ComputeHash(SignatureBytes));

    return AuthorizationHeader;
}
2
kostas 24 जिंदा 2017, 16:49
चूंकि आप साझा पहुंच हस्ताक्षर (एसएएस) का उपयोग कर रहे हैं, इसलिए आपको प्राधिकरण शीर्षलेख की आवश्यकता नहीं है। क्या आप मुझे बता सकते हैं कि आपने शेयर्ड एक्सेस सिग्नेचर कैसे बनाया? मुझे एसएएस में शामिल अनुमतियों के बारे में जानने में दिलचस्पी है।
 – 
Gaurav Mantri
24 जिंदा 2017, 17:23

2 जवाब

सबसे बढ़िया उत्तर

कृपया निम्नलिखित कोड स्निपेट पर विचार करें। यह आपके लिए काम करना चाहिए।

void UploadBlobWithRestAPI() {

    string storageKey = "<your access key here>";
    string storageAccount = "<your storage account name here>";    
    string containerName = "<your container name here>";
    string blobName = "test.txt";

    string method = "PUT";
    string sampleContent = "This is sample text.";
    int contentLength = Encoding.UTF8.GetByteCount(sampleContent);

    string requestUri = $"https://{storageAccount}.blob.core.windows.net/{containerName}/{blobName}";

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUri);

    string now = DateTime.UtcNow.ToString("R");

    request.Method = method;
    request.ContentType = "text/plain; charset=UTF-8";
    request.ContentLength = contentLength;

    request.Headers.Add("x-ms-version", "2015-12-11");
    request.Headers.Add("x-ms-date", now);
    request.Headers.Add("x-ms-blob-type", "BlockBlob");
    request.Headers.Add("Authorization", AuthorizationHeader(method, now, request, storageAccount, storageKey, containerName, blobName));

    using (Stream requestStream = request.GetRequestStream()) {
        requestStream.Write(Encoding.UTF8.GetBytes(sampleContent), 0, contentLength);
    }

    using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse()) {
        MessageBox.Show(resp.StatusCode.ToString());
    }

}

public string AuthorizationHeader(string method, string now, HttpWebRequest request, string storageAccount, string storageKey, string containerName, string blobName) {

    string headerResource = $"x-ms-blob-type:BlockBlob\nx-ms-date:{now}\nx-ms-version:2015-12-11";
    string urlResource = $"/{storageAccount}/{containerName}/{blobName}";
    string stringToSign = $"{method}\n\n\n{request.ContentLength}\n\n{request.ContentType}\n\n\n\n\n\n\n{headerResource}\n{urlResource}";

    HMACSHA256 hmac = new HMACSHA256(Convert.FromBase64String(storageKey));
    string signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));

    String AuthorizationHeader = String.Format("{0} {1}:{2}", "SharedKey", storageAccount, signature);
    return AuthorizationHeader;
}

और फ़िडलर द्वारा कैप्चर किया गया ट्रैफ़िक इस प्रकार है:

enter image description here

8
Aaron Chen 25 जिंदा 2017, 14:40
बहुत - बहुत धन्यवाद। मैंने आपके कोड की कोशिश की लेकिन मुझे एक (403) निषिद्ध त्रुटि मिल रही है
 – 
kostas
25 जिंदा 2017, 12:41
यह मेरी साइट पर ठीक काम करता है। तो क्या आप अपने प्रश्न को अपने नवीनतम कोड स्निपेट के साथ संपादित कर सकते हैं?
 – 
Aaron Chen
25 जिंदा 2017, 13:17
नमस्ते, मैंने अपनी हार्ड-कोड समस्या को ठीक करने के लिए अपना कोड अपडेट कर लिया है। क्या आप फिर से कोशिश कर सकते हैं?
 – 
Aaron Chen
25 जिंदा 2017, 14:41
हाय @kostas, यह सुनकर खुशी हुई, आप इसे उत्तर के रूप में चिह्नित कर सकते हैं, जो अन्य समुदायों की मदद करेगा जो आपके साथ इसी तरह के मुद्दे का सामना कर रहे हैं।
 – 
Aaron Chen
31 जिंदा 2017, 17:41
यह समाधान काम करता है लेकिन केवल 4 एमबी तक की फाइलों को संभालता है। रेड गेट के रॉबिन शाहन ने red-gate.com/simple-talk/cloud/platform-as-a-service/…
 – 
John Bonfardeci
10 मार्च 2021, 17:58

ऊपर दिया गया समाधान केवल 4MB आकार तक की फ़ाइलें अपलोड करता है। मुझे एक परियोजना की आवश्यकता के लिए एक पावरशेल संस्करण की आवश्यकता थी और उपरोक्त समाधान के साथ गलत राह पर चला गया। एक BLOB को Azure RBS में विभाजित करने के लिए एक कस्टम फ़ंक्शन के लिए, मैंने लाल गेट से रॉबिन शाहन के संस्करण को https://www.red-gate.com/simple-talk/cloud/platform-as-a- service/azure-blob-storage-part-4-uploading-large-blobs/.

$sdkPath = "C:/Program Files/Microsoft SDKs/Azure/.NET SDK/v2.9/bin/plugins/Diagnostics/Microsoft.WindowsAzure.Storage.dll"
[System.Reflection.Assembly]::LoadFrom($sdkPath);

Add-Type -AssemblyName System.Net.Http

function getMD5HashFromBytes([byte[]]$fileBytes){
    $md5 = [System.Security.Cryptography.MD5]::Create()
    [byte[]]$hash = $md5.ComputeHash($fileBytes)
    return [System.Convert]::ToBase64String($hash)
}

function setupBlobContainer($account, $secretKey, $container){
    $cs = [String]::Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}", $account, $secretKey)
    $cloudStorageAccount = [Microsoft.WindowsAzure.Storage.CloudStorageAccount]::Parse($cs)
    $cloudBlobClient = [Microsoft.WindowsAzure.Storage.Blob.CloudBlobClient]$cloudStorageAccount.CreateCloudBlobClient()
    $cloudBlobContainer = [Microsoft.WindowsAzure.Storage.Blob.CloudBlobContainer]$cloudBlobClient.GetContainerReference($container)
    return $cloudBlobContainer
}

function chunkBlob([string]$filepath, [string]$filename, `
    [Microsoft.WindowsAzure.Storage.Blob.CloudBlobContainer]$cloudBlobContainer){

    #ref: https://www.red-gate.com/simple-talk/cloud/platform-as-a-service/azure-blob-storage-part-4-uploading-large-blobs/

    $blob = [Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob]$cloudBlobContainer.GetBlockBlobReference($filename)
    $blockSize = 256 * 1024; #256 kb
    $fileStream = [System.IO.FileStream]::new($filepath, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite)
    $fileSize = $fileStream.Length

    #block count is the number of blocks + 1 for the last one
    $blockCount = [int]([float]$fileSize / [float]$blockSize) + 1
 
    #List of block ids; the blocks will be committed in the order of this list 
    $blockIDs = [System.Collections.Generic.List[string]]::new()
 
    #starting block number - 1
    $blockNumber = 0
 
    try
    {
        $bytesRead = 0 #number of bytes read so far
        $bytesLeft = $fileSize; #number of bytes left to read and upload
 
        #do until all of the bytes are uploaded
        while($bytesLeft -gt 0){

            $blockNumber++;

            [int]$bytesToRead;
        
            if($bytesLeft -ge $blockSize){
                #more than one block left, so put up another whole block
                $bytesToRead = $blockSize
            }
            else{
                #less than one block left, read the rest of it
                $bytesToRead = [int]$bytesLeft
            }
 
            #create a blockID from the block number, add it to the block ID list
            #the block ID is a base64 string
            $blockId = [Convert]::ToBase64String([System.Text.ASCIIEncoding]::ASCII.GetBytes([String]::Format("BlockId{0}", $blockNumber.ToString("0000000"))))
            $blockIDs.Add($blockId)
        
            #set up new buffer with the right size, and read that many bytes into it 
            [byte[]]$bytes = [System.Byte[]]::new($bytesToRead)

            $fileStream.Read($bytes, 0, $bytesToRead)
 
            #calculate the MD5 hash of the byte array
            $blockHash = getMD5HashFromBytes $bytes
 
            #upload the block, provide the hash so Azure can verify it
            $blob.PutBlock($blockId, [System.IO.MemoryStream]::new($bytes), $blockHash)
 
            #increment/decrement counters
            $bytesRead += $bytesToRead
            $bytesLeft -= $bytesToRead

            $perc = [float][math]::Round( [float]$bytesRead/[float]($bytesRead + $bytesLeft) * 100, 2)

            Write-Progress -Activity "Writing '$($filename)'..." -PercentComplete $perc
        }
 
        #commit the blocks
        $blob.PutBlockList($blockIDs)
    }
    catch [System.Exception] {
        write-warning $_
    }
    finally{
        if($fileStream){
            $fileStream.Dispose()
        }
    }
}
0
John Bonfardeci 10 मार्च 2021, 18:12