我想获取一台服务器中所有 .rdl 文件的副本。 我可以一次手动下载一份报告,但这很耗时,尤其是该服务器有大约 1500 个报告。
有什么方法或工具可以让我下载所有 .rdl 文件并获取它们的副本吗?
有一种完整且更简单的方法可以使用 PowerShell 来执行此操作。
此代码将以与报表服务器完全相同的结构导出所有报表内容。查看 Github wiki 了解其他选项和命令
#------------------------------------------------------
#Prerequisites
#Install-Module -Name ReportingServicesTools
#------------------------------------------------------
#Lets get security on all folders in a single instance
#------------------------------------------------------
#Declare SSRS URI
$sourceRsUri = 'http://ReportServerURL/ReportServer/ReportService2010.asmx?wsdl'
#Declare Proxy so we dont need to connect with every command
$proxy = New-RsWebServiceProxy -ReportServerUri $sourceRsUri
#Output ALL Catalog items to file system
Out-RsFolderContent -Proxy $proxy -RsFolder / -Destination 'C:\SSRS_Out' -Recurse
我创建了这个 powershell 脚本来将它们复制到 ZIP 中。您必须提供 SQL Server 数据库详细信息。
Add-Type -AssemblyName "System.IO.Compression.Filesystem"
$dataSource = "SQLSERVER"
$user = "sa"
$pass = "sqlpassword"
$database = "ReportServer"
$connectionString = "Server=$dataSource;uid=$user; pwd=$pass;Database=$database;Integrated Security=False;"
$tempfolder = "$env:TEMP\Reports"
$zipfile = $PSScriptRoot + '\reports.zip'
$connection = New-Object System.Data.SqlClient.SqlConnection
$connection.ConnectionString = $connectionString
$connection.Open()
$allreports = $connection.CreateCommand()
$allreports.CommandText = "SELECT ItemID, Path, CASE WHEN Type = 2 THEN '.rdl' ELSE '.rds' END AS Ext FROM Catalog WHERE Type IN(2,5)"
$result = $allreports.ExecuteReader()
$reportable = new-object "System.Data.DataTable"
$reportable.Load($result)
[int]$objects = $reportable.Rows.Count
foreach ($report in $reportable) {
$cmd = $connection.CreateCommand()
$cmd.CommandText = "SELECT CAST(CAST(Content AS VARBINARY(MAX)) AS XML) FROM Catalog WHERE ItemID = '" + $report[0] + "'"
$xmldata = [string]$cmd.ExecuteScalar()
$filename = $tempfolder + $report["Path"].Replace('/', '\') + $report["Ext"]
New-Item $filename -Force | Out-Null
Set-Content -Path ($filename) -Value $xmldata -Force
Write-Host "$($objects.ToString()).$($report["Path"])"
$objects -= 1
}
Write-Host "Compressing to zip file..."
if (Test-Path $zipfile) {
Remove-Item $zipfile
}
[IO.Compression.Zipfile]::CreateFromDirectory($tempfolder, $zipfile)
Write-Host "Removing temporarly data"
Remove-Item -LiteralPath $tempfolder -Force -Recurse
Invoke-Item $zipfile
发现并使用它没有任何问题。无需安装,只需添加我的网址,然后粘贴到 Powershell 中。
https://microsoft-bitools.blogspot.com/2018/09/ssrs-snack-download-all-ssrs-reports.html
以防链接中断,以下是链接中的代码:
###################################################################################
# Download Reports and DataSources from a SSRS server and create the same folder
# structure in the local download folder.
###################################################################################
# Parameters
###################################################################################
$downloadFolder = "c:\temp\ssrs\"
$ssrsServer = "http://myssrs.westeurope.cloudapp.azure.com"
###################################################################################
# If you can't use integrated security
#$secpasswd = ConvertTo-SecureString "MyPassword!" -AsPlainText -Force
#$mycreds = New-Object System.Management.Automation.PSCredential ("MyUser", $secpasswd)
#$ssrsProxy = New-WebServiceProxy -Uri "$($ssrsServer)/ReportServer/ReportService2010.asmx?WSDL" -Credential $mycreds
# SSRS Webserver call
$ssrsProxy = New-WebServiceProxy -Uri "$($ssrsServer)/ReportServer/ReportService2010.asmx?WSDL" -UseDefaultCredential
# List everything on the Report Server, recursively, but filter to keep Reports and DataSources
$ssrsItems = $ssrsProxy.ListChildren("/", $true) | Where-Object {$_.TypeName -eq "DataSource" -or $_.TypeName -eq "Report"}
# Loop through reports and data sources
Foreach($ssrsItem in $ssrsItems)
{
# Determine extension for Reports and DataSources
if ($ssrsItem.TypeName -eq "Report")
{
$extension = ".rdl"
}
else
{
$extension = ".rds"
}
# Write path to screen for debug purposes
Write-Host "Downloading $($ssrsItem.Path)$($extension)";
# Create download folder if it doesn't exist (concatenate: "c:\temp\ssrs\" and "/SSRSFolder/")
$downloadFolderSub = $downloadFolder.Trim('\') + $ssrsItem.Path.Replace($ssrsItem.Name,"").Replace("/","\").Trim()
New-Item -ItemType Directory -Path $downloadFolderSub -Force > $null
# Get SSRS file bytes in a variable
$ssrsFile = New-Object System.Xml.XmlDocument
[byte[]] $ssrsDefinition = $null
$ssrsDefinition = $ssrsProxy.GetItemDefinition($ssrsItem.Path)
# Download the actual bytes
[System.IO.MemoryStream] $memoryStream = New-Object System.IO.MemoryStream(@(,$ssrsDefinition))
$ssrsFile.Load($memoryStream)
$fullDataSourceFileName = $downloadFolderSub + "\" + $ssrsItem.Name + $extension;
$ssrsFile.Save($fullDataSourceFileName);
}
这是基于 SQL2016/SSRS2016 但我认为它应该适用于 2012 年。
SELECT 'http://mySQLServerName/reports/api/v1.0/catalogitems(' + cast(itemid as varchar(256))+ ')/Content/$value' AS url
FROM ReportServer.dbo.Catalog
这将为您提供一份 URL 列表,每个报告对应一个 URL。
如果上述方法在 SSRS 2012 中不起作用,请转到报告管理器并按照从那里下载文件的方式进行操作。检查下载按钮上的 URL,您可能会看到一个 URL,其中嵌入了项目 ID。只需调整上面的代码以匹配该 url 结构即可。
之后你要做什么取决于你。 就我个人而言,我会使用 Chrome 商店here中提供的名为“Tab Save”的 Chrome 扩展程序。您只需将上面创建的所有 URL 复制并粘贴到其中,然后点击下载按钮...
如果您仅需要此用于备份目的或类似目的,这可能很有用:已发布的 RDL 文件位于何处?
该线程的相关查询是:
select convert(varchar(max), convert(varbinary(max), content))
from catalog
where content is not null
最初的答案是使用2005年,我在2016年使用过它,所以我想它应该适用于2008年和2012年。
当我必须使用它时,我也将路径添加到查询中,以便我知道哪个报告是哪个。
警告:在 SSMS v18 之前,结果到网格的大小限制为每个元组 64KB,结果到文本的大小限制为每个元组 8,192 个字符。如果您的报告定义大于这些限制,您将无法获得完整的定义。
在 SSMS v18 中,对于网格报告和文本结果,这些限制已增加到每个元组 2MB。
我尝试了此脚本的几种排列,但不断收到“无法创建代理连接”错误。这是“应该”起作用的:
#------------------------------------------------------
#Prerequisites
#Install-Module -Name ReportingServicesTools
#------------------------------------------------------
#Lets get security on all folders in a single instance
#------------------------------------------------------
#Declare SSRS URI
$sourceRsUri = "http://hqmnbi:80/ReportServer_SQL08/ReportService2010.asmx?wsdl"
#Declare Proxy so we dont need to connect with every command
$proxy = New-RsWebServiceProxy -ReportServerUri $sourceRsUri
#Output ALL Catalog items to file system
Out-RsFolderContent -Proxy $proxy -RsFolder / -Destination 'C:\Users\arobinson\source\Workspaces\EDW\MAIN\SSRS\HQMNBI' -Recurse
这是我遇到的错误:
无法与 http://hqmnbi/ReportServer_SQL08/ReportService2010.asmx 建立代理连接:HTML 文档不包含 Web 服务发现信息。 在 C:\Program Files\WindowsPowerShell\Modules\ReportingServicesTools .0.6.6\Functions\Utilities\New-RsWebServiceProxy.ps1:136 char:9
throw (New-Object System.Exception("Failed to establish proxy ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
我尝试过使用 htttp:// 的 URI,也尝试过不包含端口号的 URI。等等。仍然无法让它真正发挥作用。我们还有另外两个 SSRS 实例,我可以毫无问题地运行它。
来自这个问题:SQL Reporting Services - 将报告复制到另一个文件夹
我发现这个工具既可以下载也可以上传报告。另外它还列出了文件夹和子文件夹。
关于这个问题: 无法建立与 http://hqmnbi/ReportServer_SQL08/ReportService2010.asmx 的代理连接: HTML 文档不包含 Web 服务发现信息。在 C:\Program Files\WindowsPowerShell\Modules\ReportingServicesTools .0.6.6\Functions\Utilities\New-RsWebServiceProxy.ps1:136 char:9
有同样的错误,所以我用这个代替: 而不是这一行: $sourceRsUri =“http://hqmnbi:80/ReportServer_SQL08/ReportService2010.asmx?wsdl”
用这个:
$sourceRsUri =“https://hqmnbi:80/ReportServer_SQL08/ReportService2010.asmx?wsdl”
然后一切都没有问题 - 代理和所有
我尝试使用已接受的答案,但遇到了一些问题。因此,我编写了一个脚本来使用 REST SSRS 端点。该脚本适用于 Windows 上的 Powershell 7.x。我认为如果适当更改路径分隔符,它可以在其他平台上与 Powershell 一起使用。
#------------------------------------------------------
#Prerequisites
#Install-Module -Name ReportingServicesTools
#------------------------------------------------------
$sourceRsUri = 'https://ssrs.ourcompany.com/reports'
$localRoot = 'C:\Development\MySSRSProject\Server RDL Backup'
# create all the folders first.
$folders = Get-RsRestFolderContent / -Recurse -ReportPortalUri $sourceRsUri | Where-Object Type -eq 'Folder'
foreach($folder in $folders)
{
# create each folder locally
$localFolder = $localRoot + $folder.Path
if (!(Test-Path $localFolder)) {
New-Item -ItemType Directory -Path $localFolder
}
}
# download the reports
$reports = Get-RsRestFolderContent / -Recurse -ReportPortalUri $sourceRsUri | Where-Object Type -eq 'Report'
# clear out modified date file:
Clear-Content ($localRoot + "\lastModified.txt")
foreach($report in $reports)
{
# download each report to appropriate folder
$localFolder = $localRoot + $report.Path
# replace '/' with '\' in path
$localFolder = $localFolder.Replace('/', '\')
#remove report name from path
$localFolder = $localFolder.Substring(0, $localFolder.LastIndexOf("\"))
Out-RsRestCatalogItem $report.Path -ReportPortalUri $sourceRsUri -Destination $localFolder -Overwrite
# write report last modified date and by to a file:
$outString = $report.Path + " last modified by " + $report.ModifiedBy + " on " + $report.ModifiedDate.ToString("yyyy-MM-dd HH:mm:ss")
$outString | Out-File -FilePath ($localRoot + "\lastModified.txt") -Append
}