4

我有一个 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 个参数的重载,但同样的问题也存在。

这是模块:

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);
    }
}
4

3 回答 3

2

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

[Microsoft.WindowsAzure.StorageClient.CloudBlobContainer]$blobContainer = $cloudBlobClient.GetContainerReference($Container)
$blobContainer.CreateIfNotExist() <-- Here
[Microsoft.WindowsAzure.StorageClient.CloudBlob]$blob = $blobContainer.GetBlobReference($BlobName)
$blob.UploadText($BlobText)
于 2012-09-26T18:55:13.433 回答
2

此错误非常模棱两可且具有误导性,但在某些情况下 Azure 存储可能会“混淆”。看看 Sandrino 的例子,特别是这一行,

[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是一个有效的 blob 存储实例,指向http://127.0.0.1:10000/devstoreaccount1/sggames或任何您拥有的有效容器。

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

GetBlobReference调用之后,blob 实例已损坏,现在看起来混乱的 Uri -> 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。

这是显示我描述的结果的前后图像。

坏处:

注意错误的 URI 注意错误的 URI

这个错误的 URI 破坏了实际的存储 blob 位置 这个错误的 URI 破坏了实际的存储 blob 位置

这是 dardev 的同一个例外 这是daredev的同一个例外

好的:

新的擦洗键,注意它只是 URL 查询字符串上的值 新的擦洗键,注意它只是 URL 查询字符串上的值

Azure 存储 URI 现在看起来不错 Azure 存储 URI 现在看起来不错

尤里卡! 尤里卡!

希望这可以帮助。

于 2012-11-24T22:54:10.763 回答
1

这是我用来将文件上传到 Azure Blob 的 PowerShell 脚本:上传到 Azure 存储

$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
于 2015-08-10T23:57:49.520 回答