✅ 前提整理
項目 | 内容 |
---|---|
添付対象 |
problem テーブル |
各フォルダ名 | 特定のキーワード(例:PRB0012345や「network」など) → これをServiceNow APIで検索キーに使う |
ファイル構造 | 例:C:\UploadRoot\PRB0012345\file1.pdf や C:\UploadRoot\network\log.txt
|
使用API |
GET /api/now/table/problem?sysparm_query=... でレコード検索 → POST /attachment/file で添付 |
🐋 PowerShellスクリプト案(キーワード→sys_id取得→添付)
# 認証・インスタンス設定
$Username = "your_username"
$Password = "your_password"
$Base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("$Username:$Password"))
$Instance = "your_instance.service-now.com"
$TableName = "problem"
# ルートディレクトリ(フォルダ名=キーワード)
$RootFolder = "C:\UploadRoot"
# プロキシ対応クライアント
$Handler = New-Object System.Net.Http.HttpClientHandler
$Handler.UseProxy = $true
$Handler.Proxy = [System.Net.WebRequest]::GetSystemWebProxy()
$Handler.Proxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials
$Client = New-Object System.Net.Http.HttpClient($Handler)
$Client.DefaultRequestHeaders.Authorization = [System.Net.Http.Headers.AuthenticationHeaderValue]::new("Basic", $Base64AuthInfo)
$Client.DefaultRequestHeaders.Accept.Add([System.Net.Http.Headers.MediaTypeWithQualityHeaderValue]::Parse("application/json"))
# フォルダごとに処理
Get-ChildItem -Path $RootFolder -Directory | ForEach-Object {
$Keyword = $_.Name
$FolderPath = $_.FullName
# 🔍 キーワードでレコード検索(例では「number」フィールドと一致)
$Query = "number=$Keyword" # 例: PRB0012345と一致
$SearchUrl = "https://$Instance/api/now/table/$TableName?sysparm_query=$Query&sysparm_limit=1"
$SearchResult = $Client.GetAsync($SearchUrl).Result
$JsonResult = $SearchResult.Content.ReadAsStringAsync().Result | ConvertFrom-Json
if ($JsonResult.result.Count -eq 0) {
Write-Host "⚠ レコードが見つかりません: $Keyword"
return
}
$RecordSysId = $JsonResult.result[0].sys_id
Write-Host "`n📁 [$Keyword] → sys_id: $RecordSysId"
# ファイルごとに添付
Get-ChildItem -Path $FolderPath -File | ForEach-Object {
$FilePath = $_.FullName
$FileName = $_.Name
$Url = "https://$Instance/api/now/attachment/file?table_name=$TableName&table_sys_id=$RecordSysId&file_name=$FileName"
$FileBytes = [System.IO.File]::ReadAllBytes($FilePath)
$FileContent = New-Object System.Net.Http.ByteArrayContent($FileBytes)
$FileContent.Headers.ContentDisposition = [System.Net.Http.Headers.ContentDispositionHeaderValue]::new("form-data")
$FileContent.Headers.ContentDisposition.Name = '"file"'
$FileContent.Headers.ContentDisposition.FileName = '"' + $FileName + '"'
$FileContent.Headers.ContentType = [System.Net.Http.Headers.MediaTypeHeaderValue]::Parse("application/octet-stream")
$Multipart = New-Object System.Net.Http.MultipartFormDataContent
$Multipart.Add($FileContent)
$Response = $Client.PostAsync($Url, $Multipart).Result
if ($Response.IsSuccessStatusCode) {
Write-Host "✅ $FileName を添付しました"
} else {
Write-Host "❌ $FileName の添付失敗"
$Response.Content.ReadAsStringAsync().Result
}
}
}
✅ カスタマイズ例
目的 | 方法 |
---|---|
タイトルで部分一致検索 | $Query = "short_descriptionLIKE$Keyword" |
番号で前方一致検索 | $Query = "numberSTARTSWITH$Keyword" |
キーワードをファイル名から抽出したい |
Split-Path $FilePath -LeafBase などで処理可 |
レコードが複数一致する場合の処理 |
$JsonResult.result[0] をループに変えることで対応可 |
🧪 テストのおすすめ手順
- 1件のフォルダで動作確認(例:
C:\UploadRoot\PRB0012345
) - ServiceNowで該当レコードを開き、添付ファイルが正しく表示されているか確認
- 問題なければ複数フォルダへ展開
必要であれば、
- キーワードをCSVから読み取る形式
- 添付のログ出力保存
なども対応できます。必要な方向性があればぜひ教えてください!