> For the complete documentation index, see [llms.txt](https://docs.realmjoin.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.realmjoin.com/ja/dev-reference/report-functions/publish-rjrbfilestostoragecontainer.md).

# Publish-RjRbFilesToStorageContainer

## 概要

`Publish-RjRbFilesToStorageContainer` RealmJoin のレポート用 runbook から Azure Blob Storage 経由でレポートファイル（CSV、XLSX、ZIP、…）を配信するための標準ヘルパーです。1 つ以上のローカル ファイルを対象コンテナーにアップロードし、各 blob ごとに有効期限付きの SAS ダウンロード リンクを返します。これはレポート メール、Teams メッセージ、または runbook の出力に含めるのに適しています。

主な特性:

* **いいえ `Az.Storage` 依存関係** — blob 操作は Azure Storage REST API に対して直接実行されます（コンテナー作成、アップロード、SAS token 生成）。これにより、よく知られた次のアセンブリ競合が解消されます `Az.Storage` および `ExchangeOnlineManagement` 。これは混在したレポート用 runbook で発生します。
* **自動接続** — もし `Az` context が有効でない場合、関数は透過的に `Connect-RjRbAzAccount`を呼び出します。オプションの `-SubscriptionId` により、いかなるストレージ操作より前に context を切り替えます。
* **コンテナーの自動作成** — 対象コンテナーがまだ存在しない場合は、その場で作成されます。既存のコンテナー（HTTP 409）は成功として扱われます。
* **HttpClient ベースのアップロード** — Azure Automation の `System.Net.Http.HttpClient` を直接使用します。これは Azure Automation の `Invoke-RestMethod` インターセプターが、バイナリ本文では必要なカスタム ヘッダー（`x-ms-blob-type`）を削除してしまうためです。
* **読み取り専用の SAS リンク** — 返される各 URL はストレージ アカウント キーで署名され、単一の blob にスコープされ、HTTPS のみで、 `LinkExpiryDays` 日間有効です（既定 6 日）。

通常の runbook が使用する中央のストレージ設定（リソース グループ、アカウント名、有効期限日数、blob 名プレフィックス）は RealmJoin カスタマイズ JSON にあり、 [Runbook Report Settings — Storage Account Delivery](/ja/zi-dong-hua/runbooks/runbook-report-settings.md#storage-account-delivery)に記載されています。このドキュメントでは、runbook から関数を呼び出すことに焦点を当てます。

## 前提条件

### Azure Storage Account

既存の Azure Storage Account（一般用途 v2 を推奨）が必要です。対象コンテナーは事前に存在している必要はありません — 初回使用時に自動的に作成されます。

### Azure RBAC on the storage account

Automation Account のマネージド ID（または runbook で使用する Service Principal）には、ストレージ アカウントまたはそのリソース グループに対して次の権限が必要です:

| Action                                              | 必要な対象                                |
| --------------------------------------------------- | ------------------------------------ |
| `Microsoft.Storage/storageAccounts/read`            | ストレージ アカウントの読み取り                     |
| `Microsoft.Storage/storageAccounts/listKeys/action` | SharedKey 署名と SAS 生成に使用するアカウント キーの取得 |

組み込みロール **Storage Account Contributor** は両方をカバーします。 **Storage Blob Data Contributor** 単独でも *返されません* 十分です。関数は AAD ベースの blob 操作ではなく、アカウント キーでリクエストに署名するためです。

### モジュールの接続性

この関数には `Az.Accounts` モジュールが runbook 環境で必要です（`Get-AzContext`, `Set-AzContext`, `Connect-AzAccount`, `Invoke-AzRestMethod`）。利用側の runbook で明示的に宣言してください:

```powershell
#Requires -Modules @{ModuleName = "RealmJoin.RunbookHelper"; ModuleVersion = "0.8.6" }
#Requires -Modules @{ModuleName = "Az.Accounts"; ModuleVersion = "5.3.4" }
```

この値が設定されている場合、 `Az.Accounts` がランタイムで利用できない場合、関数は明確なエラーメッセージとともに早期に失敗します — まず `Get-AzContext` を事前にチェックし、 *"Publish-RjRbFilesToStorageContainer requires the 'Az.Accounts' module. Add #Requires -Modules @{ModuleName = 'Az.Accounts'; ModuleVersion = '5.3.4'} to the calling runbook."* を Azure 呼び出しの前に投げます。

> **なぜ `Az.Accounts` は `RequiredModules` エントリとして `RealmJoin.RunbookHelper.psd1`?**
>
> `Az.Accounts` に宣言されていないのか。意図的に `ExternalModuleDependencies` の下にのみ一覧化されているためです（情報用）そして *返されません* として `RequiredModules` （ `Import-Module` 時に強制）:
>
> * **使った分だけ支払う。** 多くの runbook は Graph ベースのヘルパーのみを利用します（例: `Send-RjRbReportEmail` なしで `-UseNativeGraphRequest`、または `Invoke-RjRbRestMethodGraph`）。そして Az.\* cmdlet には一切触れません。昇格すると `Az.Accounts` から `RequiredModules` 、コード パスで必要がない場合でも、利用側のすべての runbook にそのモジュールの同梱を強制してしまい — Azure Automation におけるコールド スタート時間を測定可能なほど増やします。
> * **バージョン競合を避ける。** 厳しい `RequiredModules` 制約はインポート時の自動解決を引き起こし、特定の `Az.Accounts` バージョンを引き込んで runbook 自身が固定しているものと競合させることがあります（Az.\* のサブモジュールは非常にバージョン依存です）。runbook に独自の `#Requires -Modules` を宣言させれば、バージョンの選択権を呼び出し元に残せます。
> * **runbook ごとの権限。** Azure Automation では、モジュール要件を宣言する標準的な場所は runbook レベルの `#Requires`です。ヘルパー モジュール レベルではありません。ヘルパー モジュールは依存関係を情報として（ `ExternalModuleDependencies` マニフェスト内で）および上記のランタイム チェックにより示すため、誤設定はバージョン競合を静かに隠すのではなく、実行可能なメッセージで明確に失敗します。

`Az.Storage` が **返されません** 必要であり、上記のアセンブリ競合を避けるため、同じ runbook でインポートすべきではありません。

## クイック スタート

最小限の有効な呼び出しには、ローカル ファイル パス、コンテナー名、リソース グループ、ストレージ アカウント名が必要です:

```powershell
$csvPath = Join-Path $env:TEMP 'devices.csv'
$exportData | Export-Csv -Path $csvPath -NoTypeInformation -Encoding UTF8

$results = Publish-RjRbFilesToStorageContainer `
    -FilePaths          $csvPath `
    -ContainerName      'reports' `
    -ResourceGroupName  'rg-reports' `
    -StorageAccountName 'stcontosoreports'

$results | Format-Table BlobName, EndTime, SASLink
```

これにより `devices.csv` を `reports` コンテナー内の `stcontosoreports` にアップロードし、blob 名、SAS の有効期限タイムスタンプ、そして既定の 6 日間有効な共有可能なダウンロード URL を含む 1 つのオブジェクトを返します。

## パラメーター

### 必須

| パラメーター               | 型          | 説明                                                                                                                                        |
| -------------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `FilePaths`          | `string[]` | アップロードする 1 つ以上のローカル ファイル パス。各パスは既存のファイルを指している必要があります（`Test-Path -PathType Leaf`）。いずれかが欠けている場合、関数は事前に例外を投げます。                              |
| `ContainerName`      | `string`   | 対象の blob コンテナー。存在しない場合は自動作成されます。Azure のコンテナー命名規則（小文字、3〜63 文字、英数字 + ハイフン）に従う必要があります。コンテナー名は *runbook ごとの* 判断事項であり、中央設定ではなく runbook で設定します。 |
| `ResourceGroupName`  | `string`   | ストレージ アカウントを含むリソース グループ。通常は中央設定 `RJReport.AzureStorage.ResourceGroup`.                                                                    |
| `StorageAccountName` | `string`   | Azure Storage Account の名前。通常は中央設定 `RJReport.AzureStorage.StorageAccountName`.                                                             |

### オプションの

| パラメーター              | 型        | 既定値         | 説明                                                                                                                       |
| ------------------- | -------- | ----------- | ------------------------------------------------------------------------------------------------------------------------ |
| `SubscriptionId`    | `string` | 現在の context | ストレージ アカウントをホストする Azure サブスクリプション。指定した場合、 `Set-AzContext -Subscription` がストレージ操作の前に呼び出されます。省略すると現在の `Az` context を使用します。 |
| `LinkExpiryDays`    | `int`    | `6`         | SAS リンクの有効日数。 `[1, 3650]`で検証されます。同じ有効期限タイムスタンプが 1 回の呼び出しで全 blob に適用されます。通常は中央設定 `RJReport.AzureStorage.LinkExpiryDays`.  |
| `AddBlobNamePrefix` | `bool`   | `$false`    | 有効な場合、 `$true`blob 名の先頭に `yyyyMMdd-HHmmss-` （ `Get-Date` のアップロード時のタイムスタンプ）を付け、繰り返し実行時の上書きを防ぎます。元のファイル名は接尾辞として保持されます。     |

> **注:** これらのパラメーターと中央の RealmJoin カスタマイズ JSON（推奨既定値を含む）との対応は、 [Runbook Report Settings — Storage Account Delivery](/ja/zi-dong-hua/runbooks/runbook-report-settings.md#storage-account-delivery).

## 使用例

### 推奨 runbook パターン

に記載されています。これはレポート用 runbook で使われる標準パターンです。ストレージ設定は中央の RealmJoin カスタマイズから `Use-RJInterface -Type Setting`を通じて取得され、コンテナーは runbook ごとにハードコードされ、設定が欠けていると runbook は実行可能なメッセージとともに中断します:

```powershell
#Requires -Modules @{ModuleName = "RealmJoin.RunbookHelper"; ModuleVersion = "0.8.6" }
#Requires -Modules @{ModuleName = "Az.Accounts"; ModuleVersion = "5.3.4" }

param(
    [string] $ContainerName = "my-runbook-output",

    [ValidateScript( { Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process; Use-RJInterface -Type Setting -Attribute "RJReport.AzureStorage.ResourceGroup" } )]
    [string] $ResourceGroupName,

    [ValidateScript( { Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process; Use-RJInterface -Type Setting -Attribute "RJReport.AzureStorage.StorageAccountName" } )]
    [string] $StorageAccountName,

    [ValidateScript( { Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process; Use-RJInterface -Type Setting -Attribute "RJReport.AzureStorage.LinkExpiryDays" } )]
    [ValidateRange(1, 3650)]
    [int] $LinkExpiryDays = 6
)

Connect-RjRbAzAccount

if ((-not $ResourceGroupName) -or (-not $StorageAccountName)) {
    "## ストレージ アカウントへエクスポートするには、RJ Runbooks Customization を使用してください"
    "## ( https://portal.realmjoin.com/settings/runbooks-customizations ) で次を構成してください:"
    "##   - RJReport.AzureStorage.ResourceGroup"
    "##   - RJReport.AzureStorage.StorageAccountName"
    throw "Storage Account の構成がありません。"
}

# … エクスポート ファイルを生成 …
$exportPath = "myReport.csv"

$uploadResults = Publish-RjRbFilesToStorageContainer `
    -FilePaths          @($exportPath) `
    -ContainerName      $ContainerName `
    -ResourceGroupName  $ResourceGroupName `
    -StorageAccountName $StorageAccountName `
    -LinkExpiryDays     $LinkExpiryDays `
    -AddBlobNamePrefix  $true

$uploadResult = $uploadResults[0]
"## エクスポートを作成しました。"
"## リンクの有効期限: $($uploadResult.EndTime)"
$uploadResult.SASLink | Out-String
```

このパターンを採用する際に守っておくとよい慣例がいくつかあります:

* 3 つの中央設定（`ResourceGroup`, `StorageAccountName`, `LinkExpiryDays`）は runbook パラメーターとして公開され、via `Use-RJInterface -Type Setting`、通常は *非表示にされ* runbook customization（`"Hide": true`）にして、エンド ユーザーには見えないようにします。
* コンテナー名は runbook ごとにハードコードされ（多くは `param` の既定値を通じて）、ライフサイクル ポリシーとアクセス制御をエクスポート種別ごとに調整できるようにします — これは意図的に *返されません* 中央設定です。
* `AddBlobNamePrefix $true` は、毎回固定ファイル名を生成する定期エクスポートに対する安全な既定値です。
* この関数は runbook の मुख्य `try { … } catch { throw $_ } finally { Disconnect-AzAccount … }` ブロック内で呼び出されるため、部分的な失敗は Automation ジョブに伝播し、成功時でも Az context は解放されます。

### 1 回の呼び出しで複数ファイル

`FilePaths` 配列を受け取ります。各ファイルは順番にアップロードされ、アップロードされた各 blob ごとに結果オブジェクトが返されます。

```powershell
$results = Publish-RjRbFilesToStorageContainer `
    -FilePaths          @($csvPath, $xlsxPath) `
    -ContainerName      'reports' `
    -ResourceGroupName  $ResourceGroupName `
    -StorageAccountName $StorageAccountName

foreach ($r in $results) {
    "アップロード済み $($r.BlobName) — $($r.EndTime) までダウンロード可: $($r.SASLink)"
}
```

### カスタムなリンク有効期間と明示的なサブスクリプション

```powershell
Publish-RjRbFilesToStorageContainer `
    -FilePaths          $exportPaths `
    -ContainerName      'quarterly-reports' `
    -ResourceGroupName  $ResourceGroupName `
    -StorageAccountName $StorageAccountName `
    -SubscriptionId     '00000000-0000-0000-0000-000000000000' `
    -LinkExpiryDays     30
```

runbook が複数のサブスクリプションにまたがる場合や、後続の受信者に既定の 6 日より長い期間が必要な場合に便利です。

### と組み合わせる `Send-RjRbReportEmail`

一般的なパターンは、大きなデータを blob storage にアップロードし、SAS リンクをレポート メールに埋め込んで、メールを Graph の `sendMail` 制限より十分に小さく保つことです:

```powershell
$uploaded = Publish-RjRbFilesToStorageContainer `
    -FilePaths          $csvPath `
    -ContainerName      'reports' `
    -ResourceGroupName  $ResourceGroupName `
    -StorageAccountName $StorageAccountName `
    -AddBlobNamePrefix  $true

$linkLine = "[Download {0}]({1}) (valid until {2:yyyy-MM-dd HH:mm} UTC)" -f `
    $uploaded[0].BlobName, $uploaded[0].SASLink, $uploaded[0].EndTime.ToUniversalTime()

$reportMd = @"
# デバイス インベントリ

完全なデバイス一覧はダウンロードとして利用できます:

$linkLine
"@

Send-RjRbReportEmail `
    -EmailFrom       $emailFrom `
    -EmailTo         'it-reports@contoso.com' `
    -Subject         "Device Inventory — $(Get-Date -Format 'yyyy-MM-dd')" `
    -MarkdownContent $reportMd
```

参照 [Send-RjRbReportEmail](/ja/dev-reference/report-functions/send-rjrbreportemail.md) このパターンのメール側に対して。

## 動作とエラー処理

### 事前のファイル検証

Azure 呼び出しが行われる前に、関数は `FilePaths` を走査し、 `File '<path>' が見つかりませんでした。` 最初に見つからない項目で例外を投げます。これにより、呼び出し側が টাইपोを渡した場合の部分アップロードを防ぎます。

### Azure context の解決

`Get-AzContext` が最初に確認されます。context が存在しないか、context に `Account` （たとえば新しい runbook 実行）の場合、関数は `Connect-RjRbAzAccount` を呼び出してマネージド ID を認証します。もし `-SubscriptionId` が指定されると、 `Set-AzContext -Subscription` が次に呼び出されます。

### コンテナー作成

コンテナーは `PUT …?restype=container` リクエストで作成されます:

* **HTTP 201** — コンテナーが作成されました。
* **HTTP 409** — コンテナーは既に存在します。成功として扱われます。
* **その他のステータス** — 関数は `コンテナー作成に失敗しました (<status>): <body>`.

### アップロード失敗

各ファイルは `HttpClient.SendAsync`を介してアップロードされます。成功以外のステータスになると、呼び出しは `blob アップロードに失敗しました (<status>): <body>`で終了します。これには Azure Storage が返した生のエラーも含まれます。同じ呼び出しですでにアップロード済みの前のファイルはストレージ アカウント上に残ります — 部分的なアップロードが許容できない場合、呼び出し側は try/catch で呼び出しを包み、クリーンアップを実行するとよいでしょう。

### キー取得の失敗

`Invoke-AzRestMethod` ARM の `listKeys` エンドポイントを呼び出すために使用されます。応答ステータスが 200 以外なら、関数は `リソース グループ '<rg>' の '<account>' に対するストレージ アカウント キーの取得に失敗しました。ステータス: <status>`を投げます。最も一般的な原因は次のとおりです:

* 不足している `Microsoft.Storage/storageAccounts/listKeys/action` managed identity 上の RBAC。
* サブスクリプション コンテキストの誤り（ `-SubscriptionId`).
* の入力ミス `StorageAccountName` または `ResourceGroupName`.
* 中央設定が `RJReport.AzureStorage.ResourceGroup` / `RJReport.AzureStorage.StorageAccountName` 未設定 — 参照してください [ランブック レポート設定](/ja/zi-dong-hua/runbooks/runbook-report-settings.md#storage-account-delivery).

### SAS token の特性

生成される token は次を使用します:

* `sv=2023-11-03` （署名バージョン）
* `sr=b` （blob スコープ）
* `sp=r` （読み取り専用）
* `spr=https` （HTTPS のみ）
* `st` は 5 分過去に設定され（時計ずれの許容） `se` から `LinkExpiryDays` は呼び出し時点からの期間です。

token はストレージ アカウント キーで署名されます。 **リンクを知っている人は、有効期限まで blob をダウンロードできます** — 返された SAS URL は秘密情報として扱ってください。

## 出力

各成功したアップロードは `PSCustomObject` を生成し、次のプロパティを持ちます:

| Property   | 型          | 説明                                                                                 |
| ---------- | ---------- | ---------------------------------------------------------------------------------- |
| `BlobName` | `string`   | コンテナー内の最終的な blob 名です。タイムスタンプ プレフィックスがある場合はそれも含まれます。 `AddBlobNamePrefix` が `$true`. |
| `EndTime`  | `datetime` | ローカル時刻の SAS 有効期限（URL には UTC としてもエンコードされます）。                                        |
| `SASLink`  | `string`   | 埋め込み SAS token を含む完全修飾 HTTPS ダウンロード URL。                                           |

結果は `FilePaths`と同じ順序で返されます。単一ファイルをアップロードする場合でも戻り値は配列です — それをインデックス付けする（`$results[0]`）か、 `foreach` で反復し、スカラーとして扱わないでください。

## 関連項目

* [Runbook Report Settings — Storage Account Delivery](/ja/zi-dong-hua/runbooks/runbook-report-settings.md#storage-account-delivery) — レポート用 runbook で使用される、ストレージ アカウント、リンク有効期限、blob 名プレフィックスの中央設定。
* [Send-RjRbReportEmail](/ja/dev-reference/report-functions/send-rjrbreportemail.md) — メールでレポートを配信するための補助ヘルパー。メールのペイロードを小さく保つため、この関数とよく組み合わせて使われます。
* Microsoft Docs: [Shared Key で認証する](https://learn.microsoft.com/en-us/rest/api/storageservices/authorize-with-shared-key) — このヘルパーで使用される署名方式。
* Microsoft Docs: [サービス SAS を作成する](https://learn.microsoft.com/en-us/rest/api/storageservices/create-service-sas) — 返される SAS token 形式 `SASLink`.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.realmjoin.com/ja/dev-reference/report-functions/publish-rjrbfilestostoragecontainer.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
