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

一般的な runbook で使用される中央の storage 設定（resource group、account name、expiry days、blob-name prefix）は RealmJoin customization 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 を推奨）が必要です。対象コンテナーは事前に存在している必要はありません。初回使用時に自動作成されます。

### storage account に対する Azure RBAC

Automation Account の managed identity（または runbook で使用する Service Principal ）には、storage account またはその resource group に対して次の権限が必要です:

| アクション                                               | 必要な用途                                     |
| --------------------------------------------------- | ----------------------------------------- |
| `Microsoft.Storage/storageAccounts/read`            | storage account の読み取り                     |
| `Microsoft.Storage/storageAccounts/listKeys/action` | SharedKey 署名と SAS 生成に使用する account key の取得 |

組み込みロールの **Storage Account Contributor** の両方をカバーします。 **Storage Blob Data Contributor** だけでは *不十分です* なぜなら、この関数は AAD ベースの blob 操作ではなく account key で要求に署名するためです。

### モジュール接続性

この関数には `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 には 'Az.Accounts' モジュールが必要です。呼び出し元の runbook に #Requires -Modules @{ModuleName = 'Az.Accounts'; ModuleVersion = '5.3.4'} を追加してください。"* いかなる 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 の cold-start 時間が目に見えて増加します。
> * **バージョン競合を避けます。** 厳格な `RequiredModules` 制約は import 時に自動解決を引き起こし、特定の `Az.Accounts` runbook 自身が固定しているものと競合する version を引き込む可能性があります（Az.\* サブモジュールは非常にバージョン依存が強いことで知られています）。runbook 自身に `#Requires -Modules` を宣言させることで、version の選択を呼び出し側に残せます。
> * **runbook ごとの権限。** Azure Automation では、モジュール要件を宣言する標準的な場所は runbook レベルの `#Requires`であり、ヘルパーモジュールのレベルではありません。ヘルパーモジュールは依存関係を情報として（ `ExternalModuleDependencies` manifest 内で）および上記の実行時チェックで示すため、設定ミスは version 競合を静かに隠すのではなく、実行可能なメッセージとともに明確に失敗します。

`Az.Storage` は **不十分です** 必須であり、上記の assembly 競合を避けるため同じ runbook で import しないでください。

## クイック スタート

最低限必要な呼び出しには、ローカルファイルのパス、コンテナー名、resource group、および storage account 名が必要です:

```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`   | storage account を含む resource group。通常は次の中央設定に紐づきます: `RJReport.StorageAccount.ResourceGroup`.                                               |
| `StorageAccountName` | `string`   | Azure Storage Account の名前。通常は次の中央設定に紐づきます: `RJReport.StorageAccount.StorageAccountName`.                                                   |

### オプション

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

> **注意:** これらのパラメーターと中央の RealmJoin customization JSON との対応（推奨既定値を含む）は次で説明されています: [Runbook Report Settings — Storage Account Delivery](/ja/zi-dong-hua/runbooks/runbook-report-settings.md#storage-account-delivery).

## 使用例

### 推奨 runbook パターン

これは reporting runbook で使われる標準的なパターンです。storage 設定は中央の RealmJoin customization から次を介して取得されます: `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.StorageAccount.ResourceGroup" } )]
    [string] $ResourceGroupName,

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

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

Connect-RjRbAzAccount

if ((-not $ResourceGroupName) -or (-not $StorageAccountName)) {
    "## storage account へエクスポートするには、RJ Runbooks Customization を使用してください"
    "## （ https://portal.realmjoin.com/settings/runbooks-customizations ）で次を設定してください:"
    "##   - RJReport.StorageAccount.ResourceGroup"
    "##   - RJReport.StorageAccount.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 パラメーターとして公開され、次を介して紐づけられます: `Use-RJInterface -Type Setting`、ただし通常は *非表示にされます* runbook customization 内で（`"Hide": true`）そのため、エンドユーザーには表示されません。
* コンテナー名は runbook ごとにハードコードされます（多くの場合、次の `param` の既定値を通じて）。これにより、ライフサイクル ポリシーとアクセス制御をエクスポート種別ごとに調整できます。これは意図的に *不十分です* 中央設定ではありません。
* `AddBlobNamePrefix $true` は、毎回固定ファイル名を生成する定期エクスポートに対する安全な既定値です。
* この関数は runbook のメインの `try { … } catch { throw $_ } finally { Disconnect-AzAccount … }` ブロック内で呼び出されるため、部分的な失敗は Automation ジョブに伝播し、成功時でも Az コンテキストが解放されます。

### 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 が複数の subscription にまたがる場合や、後続の受信者が 6 日の既定値より長い期間を必要とする場合に便利です。

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

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

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

$linkLine = "[Download {0}]({1}) (有効期限 {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 コンテキストの解決

`Get-AzContext` が最初に確認されます。コンテキストがない、またはコンテキストに `Account` （たとえば、runbook を新規実行した場合）、関数は次を呼び出します: `Connect-RjRbAzAccount` managed identity を認証するためです。もし `-SubscriptionId` が指定されている場合、 `Set-AzContext -Subscription` が次に呼び出されます。

### コンテナーの作成

コンテナーは次のものを使って作成されます: `PUT …?restype=container` リクエスト:

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

### アップロード失敗

各ファイルは次を介してアップロードされます: `HttpClient.SendAsync`。成功以外のステータスの場合、呼び出しは次で終了します: `Blob のアップロードに失敗しました (<status>): <body>`、Azure Storage が返した生のエラーも含みます。同じ呼び出し内で既にアップロード済みの前のファイルは storage account に残ります。部分的なアップロードが許容できない場合、呼び出し側は try/catch で呼び出しを囲み、クリーンアップを実行したくなるかもしれません。

### キー取得の失敗

`Invoke-AzRestMethod` ARM を呼び出すために使用されます: `listKeys` エンドポイント。応答ステータスが 200 以外の場合、関数は次をスローします: `resource group '<rg>' の '<account>' に対する storage account keys の取得に失敗しました。Status: <status>`。一般的な原因は次のとおりです:

* 不足している `Microsoft.Storage/storageAccounts/listKeys/action` managed identity の権限。
* サブスクリプション コンテキストの誤り（次と組み合わせるとよいです: `-SubscriptionId`).
* の টাইपो `StorageAccountName` または `ResourceGroupName`.
* 中央設定が `RJReport.StorageAccount.ResourceGroup` / `RJReport.StorageAccount.StorageAccountName` 設定されていません — 参照: [Runbook レポート設定](/ja/zi-dong-hua/runbooks/runbook-report-settings.md#storage-account-delivery).

### SAS token の特性

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

* `sv=2023-11-03` （署名済み version）
* `sr=b` （blob スコープ）
* `sp=r` （読み取り専用）
* `spr=https` （HTTPS のみ）
* `st` を 5 分前に設定し（時計ずれの許容）、 `se` に昇格させると `LinkExpiryDays` 呼び出し時刻から

Token は storage account key で署名されます。 **リンクを持つ人は有効期限まで blob をダウンロードできます** — 返された SAS URL は秘密情報として扱ってください。

## 出力

成功したアップロードごとに次が生成されます: `PSCustomObject` これらのプロパティを持つ:

| プロパティ      | 型        | 説明                                                                         |
| ---------- | -------- | -------------------------------------------------------------------------- |
| `BlobName` | `string` | コンテナー内の最終的な blob 名。タイムスタンプ接頭辞がある場合はそれも含みます。 `AddBlobNamePrefix` は `$true`. |
| `終了時刻`     | `日時`     | ローカル時刻の 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) — レポート用 runbooks で使用される Storage Account、リンクの有効期限、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.
