Вопрос или проблема
У меня есть канал Teams, где мне нужно скопировать сообщения в другой канал. Я использую MS Graph API. Попытка скопировать HostedContent (3 встроенных тега img) вызывает ошибку. В совокупности они превышают предел размера потока в 4194304.
Создание сообщения без размещенного контента, а затем обновление этого сообщения 3 раза с каждым содержимым не работает.
Как мне скопировать размещенные материалы?
(было бы здорово, если бы я мог сделать новый пост от имени оригинального пользователя)
$val="$value"
$quot="""
$msgbody = $msg.body.content
$uri = "$url/teams/$srcteamid/channels/$srcchannelid/messages/$($msg.id)/hostedContents"
$hostedContents = (Invoke-MgGraphRequest -Uri $uri -Method GET).value
if ($hostedContents -ne $null) {
ForEach ($hc in $hostedContents) {
$uri = "$url/teams/$srcteamid/channels/$srcchannelid/messages/$($msg.id)/hostedContents/$($hc.id)/$val"
Invoke-MgGraphRequest -Uri $uri -Method GET -OutputFilePath "$($hc.id).png"
}
$HostedContentArray = @()
$img = 0
$totsize = 0
$idx = 1
While ($idx -lt $hostedContents.Length) {
$hc = $hostedContents[$idx]
$contentid = $hc.id
$imgsize = (Get-Item "$contentid.png").Length
if ($totsize + $imgsize -le 4194304) {
$totsize += $imgsize
$img++
$txt = "$url/teams/$srcteamid/channels/$srcchannelid/messages/$($msg.id)/hostedContents/$contentid/$val"
$txt = $txt.replace(".", "\.").replace("/", "\/").replace("$", "\$")
$patt = "src=$quot$txt$quot"
$msgbody = $msgbody -replace $patt, "src=$quot../hostedContents/$img/$val$quot"
$obj = @{
"@microsoft.graph.temporaryId" = "$img"
contentBytes = [System.Convert]::ToBase64String([IO.File]::ReadAllBytes("$contentid.png"))
contentType = "image/png"
}
$HostedContentArray += $obj
}
$idx++
}
}
$msg_datetime = [TimeZoneInfo]::ConvertTimeBySystemTimeZoneId($msg.createdDateTime, 'Eastern Standard Time')
$msg_subject = "ON $msg_datetime, $($msg.from.user.displayName) posted: $($msg.subject)"
$uri = "$url/teams/$destteamid/channels/$destchannelid/messages"
$params = @{
subject = $msg_subject
body = @{
contentType = $msg.body.contentType
content = $msgbody
}
importance = $msg.importance
mentions = $msg.mentions
from = $msg.from
}
if ($HostedContentArray.length -gt 0) {
$params.hostedContents = $HostedContentArray
}
$dest_msg = Invoke-MgGraphRequest -Uri $uri -Method POST -Body $params
$msgbody = $dest_msg.body.content
$img = 0
$idx = 0
$HostedContentArray = @()
$hc = $hostedContents[$idx]
$contentid = $hc.id
$img++
$txt = "$url/teams/$srcteamid/channels/$srcchannelid/messages/$($msg.id)/hostedContents/$contentid/$val"
$txt = $txt.replace(".", "\.").replace("/", "\/").replace("$", "\$")
$patt = "src=$quot$txt$quot"
$msgbody = $msgbody -replace $patt, "src=$quot../hostedContents/$img/$val$quot"
$obj = @{
"@microsoft.graph.temporaryId" = "$img"
contentBytes = [System.Convert]::ToBase64String([IO.File]::ReadAllBytes("$contentid.png"))
contentType = "image/png"
}
$HostedContentArray += $obj
$params = @{
subject = $msg_subject
body = @{
contentType = $msg.body.contentType
content = $msgbody
}
hostedContents = $HostedContentArray
}
$uri = "$url/teams/$destteamid/channels/$destchannelid/messages/$($dest_msg.id)"
Invoke-MgGraphRequest -Uri $uri -Method PATCH -Body $params
Ответ или решение
Когда вы пытаетесь скопировать POST сообщения из одного канала Teams в другой с помощью Microsoft Graph API, могут возникнуть проблемы, связанные с ограничением размера для вложенного содержимого, особенно если у вас есть несколько изображений, которые в сумме превышают 4,194,304 байт. Давайте разберемся, как вы можете успешно перенести эти данные.
Проблема копирования HostedContent в Teams
Ваша основная проблема заключается в том, что при попытке копирования всех изображений (HostedContent) вы выходите за установленный предел размера. В данном случае это может быть связано с тем, что не удается успешно обновить POST-сообщение несколько раз, чтобы добавить все изображения.
Решение проблемы
Вот шаги, которые вы можете предпринять, чтобы облегчить процесс копирования HostedContent:
-
Разделение содержимого: Если у вас несколько изображений, попробуйте разбить их на группы и отправлять каждую группу по отдельности, так чтобы общая длина не превышала максимальный размер потока. Например, вы можете отправлять по два изображения за раз в новом сообщении, а если вы хотите, чтобы все контенты были вместе, то создавайте новый пост с меньшим количеством изображений.
-
Использование временного идентификатора: Убедитесь, что вы присваиваете временные идентификаторы (temporaryId) каждому изображению и что ссылки на изображения обновлены правильно в теле сообщения. Это важно для обеспечения корректного отображения изображений в новом сообщении.
-
Контент, созданный пользователем: Чтобы сделать новый пост от имени оригинального пользователя, вы можете включить объект
from
в ваши параметры при отправке нового сообщения. Убедитесь, что вы используете правильные идентификаторы и данные пользователя.
Пример кода
В вашем коде уже используется подход с получением ссылок на изображения и обработкой их перед отправкой. Однако, необходимо убедиться, что отдельные запросы на изменение не превышают лимита.
Вот некоторый рефактированный код, который можно использовать:
# Начальная инициализация
$val = "$value"
$quot = """"
$msgbody = $msg.body.content
# Получение HostedContents
$uri = "$url/teams/$srcteamid/channels/$srcchannelid/messages/$($msg.id)/hostedContents"
$hostedContents = (Invoke-MgGraphRequest -Uri $uri -Method GET).value
if ($hostedContents -ne $null) {
$HostedContentArray = @()
$totsize = 0
$img = 1
foreach ($hc in $hostedContents) {
$imgSize = (Invoke-MgGraphRequest -Uri "$url/teams/$srcteamid/channels/$srcchannelid/messages/$($msg.id)/hostedContents/$($hc.id)/$val" -Method GET -OutputFilePath "$($hc.id).png").Length
if ($totsize + $imgSize -gt 4194304) {
# Отправка сообщений с текущим набором изображений перед добавлением новых
SendMessageToTeams $msgbody $HostedContentArray
$HostedContentArray = @() # Очистка массива для новых изображений
$totsize = 0 # Сброс общего размера
}
# Добавление изображения в массив
$totsize += $imgSize
$contentBytes = [System.Convert]::ToBase64String([IO.File]::ReadAllBytes("$($hc.id).png"))
$HostedContentArray += @{
"@microsoft.graph.temporaryId" = "$img"
contentBytes = $contentBytes
contentType = "image/png"
}
$img++
}
# Отправка оставшихся изображений
if ($HostedContentArray.Count -gt 0) {
SendMessageToTeams $msgbody $HostedContentArray
}
}
# Функция для отправки сообщения в Teams
function SendMessageToTeams($msgbody, $HostedContentArray) {
$msg_subject = "ON $($msg.createdDateTime), $($msg.from.user.displayName) posted: $($msg.subject)"
$uri = "$url/teams/$destteamid/channels/$destchannelid/messages"
$params = @{
subject = $msg_subject
body = @{
contentType = $msg.body.contentType
content = $msgbody
}
hostedContents = $HostedContentArray
importance = $msg.importance
mentions = $msg.mentions
from = $msg.from
}
Invoke-MgGraphRequest -Uri $uri -Method POST -Body $params
}
Заключение
Описанный подход должен помочь вам успешно перенести содержимое сообщений, сохраняя порядок и оформление. Следите за размерами и при наличии необходимости разбивайте ваши запросы. Это улучшит совместимость с ограничениями Microsoft Graph API и обеспечит корректную передачу данных.
Если у вас возникнут дополнительные вопросы или потребуется более подробная помощь, не стесняйтесь обращаться!