上传blob文本到Azure的PowerShell错误:UploadText(string)

时间:2012-09-26 17:30:10

标签: powershell azure

我有一个powershell模块,它试图将blob上传到azure存储。一切都会检出,直到实际上传blob的最后一行。

我收到以下错误:

Exception calling "UploadText" with "1" argument(s): 
"The specified resource does not exist."
At line:1 char:1
    + $blob.UploadText("asdasdfsdf")
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : StorageClientException

我也试过使用带有3个args的重载,但同样存在同样的问题。

这是模块:

Function Add-BlobText
{
[CmdletBinding()]
param(
      [Parameter(Mandatory = $true,Position = 0)]
      [string]
      $StorageAccount,

      [Parameter(Mandatory = $true,Position = 1)]
      [string]
      $Container,

      [Parameter(Mandatory = $true,Position = 2)]
      [string]
      $BlobName,

      [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
      [string]
      $BlobText
) #end param

Add-Type -Path "C:\Assemblies\Microsoft.WindowsAzure.StorageClient.dll"

Set-AzureSubscription -SubscriptionName "MySubName"

$secondaryKey = (Get-AzureStorageKey -StorageAccountName $storageAccount).Secondary

$creds = New-Object Microsoft.WindowsAzure.StorageCredentialsAccountAndKey($StorageAccount,$secondaryKey)

$cloudStorageAccount = New-Object Microsoft.WindowsAzure.CloudStorageAccount($creds, $true)

[Microsoft.WindowsAzure.StorageClient.CloudBlobClient]$cloudBlobClient = New-Object Microsoft.WindowsAzure.StorageClient.CloudBlobClient($cloudStorageAccount.BlobEndpoint)

[Microsoft.WindowsAzure.StorageClient.CloudBlobContainer]$blobContainer = $cloudBlobClient.GetContainerReference($Container)

[Microsoft.WindowsAzure.StorageClient.CloudBlob]$blob = $blobContainer.GetBlobReference($BlobName)

$blob.UploadText($BlobText)     

} #end Function Add-BlobText

更新

我已经能够将其作为二进制模块(下面)。如果有人能够弄清楚为什么UploadText()在二进制模块中工作但在脚本模块中抛出异常,请告诉我。

[Cmdlet(VerbsCommon.Add, "BlobText")]
public class AddBlobText : PSCmdlet
{
    [Parameter(Mandatory = true, Position = 0)]
    public string StorageAccount { get; set; }

    [Parameter(Mandatory = true, Position = 1)]
    public string Container { get; set; }

    [Parameter(Mandatory = true, Position = 2)]
    public string BlobName { get; set; }

    [Parameter(Mandatory = true, ValueFromPipeline = true)]
    public string BlobText { get; set; }

    protected override void ProcessRecord()
    {
        PowerShell ps = PowerShell.Create();
        ps.AddScript("Set-AzureSubscription -SubscriptionName 'MySubName'");
        string keyScript = "( Get-AzureStorageKey -StorageAccountName " + StorageAccount + " ).Secondary";
        ps.AddScript(keyScript);
        Collection<PSObject> result = ps.Invoke();
        string secondaryKey = result[0].ToString();
        StorageCredentialsAccountAndKey credentials = new StorageCredentialsAccountAndKey(StorageAccount, secondaryKey);
        CloudStorageAccount storageAccount = new CloudStorageAccount(credentials, true);
        CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
        CloudBlobContainer container = blobClient.GetContainerReference(Container);
        var blob = container.GetBlobReference(BlobName);
        blob.UploadText(BlobText);
    }
}

3 个答案:

答案 0 :(得分:2)

这可能是因为您的容器不存在。初始化容器后,应该调用CreateIfNotExist以确保它存在:

[Microsoft.WindowsAzure.StorageClient.CloudBlobContainer]$blobContainer = $cloudBlobClient.GetContainerReference($Container)
$blobContainer.CreateIfNotExist() <-- Here
[Microsoft.WindowsAzure.StorageClient.CloudBlob]$blob = $blobContainer.GetBlobReference($BlobName)
$blob.UploadText($BlobText)

答案 1 :(得分:2)

此错误非常模糊且具有误导性,但有些实例“Azure存储可能会”混淆“。看看桑德里诺的例子,特别是这一行,

[Microsoft.WindowsAzure.StorageClient.CloudBlob]$blob = $blobContainer.GetBlobReference($BlobName)

并非Sandrino的答案是您的问题,但是在将一个Url或其他令人困惑的密钥字符串传递给Azure存储容器时会遇到您遇到的异常。

不幸的是,我不是Powershell的人,但这是一个复制示例然后修复C#。

    public void Save(string objId, T obj)
    {
        CloudBlob blob = this.container.GetBlobReference(objId); // Problematic if a URL
        blob.Properties.ContentType = "application/json";

        var serialized = string.Empty;
        serialized = serializer.Serialize(obj);

        if (this.jsonpSupport)
        {
            serialized = this.container.Name + "Callback(" + serialized + ")";
        }
        blob.UploadText(serialized);
    }

假设 this.container 是指向 http://127.0.0.1:10000/devstoreaccount1/sggames 的有效blob存储实例或任何有效容器的实例。

objId 是一个包含 https://www.google.com/accounts/o8/id?id=AItOawk4Dw9sLxSc-zmdWQHdZNcyzkTcvKUkhiE 等网址的密钥......是的,这可能会发生,在我的情况下,这是一个实际的身份声明来自谷歌使用Azure ACS。

GetBlobReference 调用之后,blob实例已经损坏,现在看着乱糟糟的Uri - &gt; https://www.google.com/accounts/o8/id?id=AItOawk4Dw9sLxSc-zmdWQHdZNcyzkTcvKUkhiE

不幸的是,简单地调用 $ blobContainer.CreateIfNotExist()的解决方案不是解决方案,也不起作用。包含Uri结构的键将仅用于重新解释blob存储位置。

解决方案(除了daredev的更新)将是这样的:

if (Uri.IsWellFormedUriString(claim, UriKind.Absolute) && HttpUtility.ParseQueryString(claim).Count > 0)
{
    claim = HttpUtility.ParseQueryString(claim)[0];
}

在上面的方法中添加此代码以清理任何Uri,但如果您需要维护完整密钥,则可以使用任何适当的方法,如Base64编码URL。

以下是显示我所描述的结果的前后图像。

糟糕:

notice the bad URI 注意坏URI

this bad URI munged up the actual storage blob location 这个坏的URI扩大了实际的存储blob位置

here is the same exception dardev had 这是daredev的相同例外

好处:

the new scrubbed key, notice it's just the value on the URL's query string 新刷新的密钥,请注意它只是URL查询字符串上的值

Azure Storage URI looks good now Azure存储URI现在看起来不错

Eureka! 尤里卡!

希望这有帮助。

答案 2 :(得分:1)

这是我用来将文件上传到Azure Blob的PowerShell脚本:Uploading to Azure Storage

$SubscriptionName = ""
$SubscriptionId = ""
$DestContainer = ""
$StorageAccountName = ""
Import-AzurePublishSettingsFile -PublishSettingsFile "<Location of the publishsettings-file>"
Set-AzureSubscription -SubscriptionId $SubscriptionId -CurrentStorageAccountName $StorageAccountName
Select-AzureSubscription -SubscriptionName $SubscriptionName
Set-AzureStorageBlobContent -File "<File you want to upload>" -Container $DestContainer