我已经看过许多使用Web API从存储在磁盘上的文件返回PDF(或其他文件类型)的示例。但是,在我的情况下,我尝试使用SSRS的URL访问动态生成文档。以下是URL的示例:
https://reporting.mydomain.biz/_layouts/ReportServer/RSViewerPage.aspx?rv:RelativeReportUrl=%2fquest%2fQUEST%2520Reports%2fReview.rdl&rp%3aReview=220
我尝试过多种方法,但其中大多数都是在2012年,并且与ASP.Net MVC
相关,例如:
public async Task<FileStreamResult> GenerateReport()
{
CredentialCache credentialCache = new CredentialCache();
credentialCache.Add(new Uri("http://domainORipaddress"), "NTLM", new NetworkCredential(
ConfigurationManager.AppSettings["username"],
ConfigurationManager.AppSettings["password"]
));
Stream report = null;
using (var httpClient = new HttpClient(new HttpClientHandler { Credentials = credentialCache }))
{
httpClient.Timeout = TimeSpan.FromMilliseconds(Timeout.Infinite);
report = await httpClient.GetStreamAsync("reportUrl");
}
var contentDisposition = new ContentDisposition
{
FileName = "Report.pdf",
Inline = false
};
Response.AppendHeader("Content-Disposition", contentDisposition.ToString());
return File(report, "application/pdf");
//or use
//Response.AppendHeader("Content-Disposition", String.Format("attachment;filename=\"{0}\"", reportName));
//return File(reportPath, MediaTypeNames.Application.Pdf);
}
此示例代码来自此网站:http://webstackoflove.com/sql-server-reporting-service-with-asp-net-mvc/
这是一个类似的问题,但基于ASP.NET
:Reporting services: Get the PDF of a generated report
我尝试使用上面的代码返回HttpResponseMessage
,但我找回了没有数据的文件。
以下是我现在使用的内容,并且它返回的文件为0 KB:
public HttpResponseMessage PrintQualityReview([FromUri] int reviewId)
{
var reportUrl = String.Format("https://reporting.mydomain.biz/quest/_vti_bin/reportserver?https://reporting.mydomain.biz/quest/QUEST%20Reports/{0}Review.rdl&rs:Format=PDF&Review={1}",
ConfigurationManager.AppSettings["ReportingServiceDatabase"],
reviewId);
CredentialCache credentialCache = new CredentialCache();
credentialCache.Add(new Uri("https://reporting.mydomain.biz"), "NTLM", new NetworkCredential(
ConfigurationManager.AppSettings["ReportingServiceAccount"],
ConfigurationManager.AppSettings["ReportingServiceAccountPwd"]
));
MemoryStream mStream = new MemoryStream();
using (WebClient wc = new WebClient())
{
wc.Credentials = credentialCache;
using (Stream stream = wc.OpenRead(reportUrl))
{
stream.CopyTo(mStream);
}
}
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StreamContent(mStream);
response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/pdf");
response.Content.Headers.ContentDisposition.FileName = "Report.pdf";
return response;
}
我想知道如何使用ASP.Net Web API
完成他的工作?
答案 0 :(得分:0)
获得0字节的原因是因为您没有设置响应头的ContentLength
。
这是您更新的代码
public HttpResponseMessage PrintQualityReview([FromUri] int reviewId) {
var reportUrl = String.Format("https://reporting.mydomain.biz/quest/_vti_bin/reportserver?https://reporting.mydomain.biz/quest/QUEST%20Reports/{0}Review.rdl&rs:Format=PDF&Review={1}",
ConfigurationManager.AppSettings["ReportingServiceDatabase"],
reviewId);
CredentialCache credentialCache = new CredentialCache();
credentialCache.Add(new Uri("https://reporting.mydomain.biz"), "NTLM", new NetworkCredential(
ConfigurationManager.AppSettings["ReportingServiceAccount"],
ConfigurationManager.AppSettings["ReportingServiceAccountPwd"]
));
MemoryStream mStream = new MemoryStream();
using (WebClient wc = new WebClient()) {
wc.Credentials = credentialCache;
using (Stream stream = wc.OpenRead(reportUrl)) {
stream.CopyTo(mStream);
}
}
var contentLength = mStream.Length; //content length for header
var contentType = new MediaTypeHeaderValue("application/pdf");
var contentDispositionValue = "attachment; filename=Report.pdf";
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StreamContent(mStream);
response.Content.Headers.ContentType = contentType;
response.Content.Headers.ContentLength = contentLength;
ContentDispositionHeaderValue contentDisposition = null;
if (ContentDispositionHeaderValue.TryParse(contentDispositionValue , out contentDisposition)) {
response.Content.Headers.ContentDisposition = contentDisposition;
}
return response;
}
答案 1 :(得分:0)
Unfortunately, simply adding content-length to the header didn't do the trick. The trick was to have the AngularJS $http service return an ArrayBuffer response.
Web API
update data1
set full_text = (regexp_matches(full_text, 'I [0-9]{1,3}'))[1]
where full_text ~ 'I [0-9]{1,3}'
AngularJS
In the controller:
[System.Web.Http.HttpGet]
[System.Web.Http.Route("api/print/qualityreview/{reviewId:int}")]
public HttpResponseMessage PrintQualityReview([FromUri] int reviewId)
{
logger.Info("Printing quality review for QR Id {0}", reviewId);
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.BadRequest);
var reportUrl = String.Format("https://example.com/quest/_vti_bin/reportserver?https://example.com/quest/QUEST%20Reports/{0}Review.rdl&rs:Format=PDF&Review={1}",
ConfigurationManager.AppSettings["ReportingServiceDatabase"],
reviewId);
CredentialCache credentialCache = new CredentialCache();
credentialCache.Add(new Uri("https://example.com"), "NTLM", new NetworkCredential(
ConfigurationManager.AppSettings["ReportingServiceAccount"],
ConfigurationManager.AppSettings["ReportingServiceAccountPwd"]
));
using (WebClient webClient = new WebClient())
{
webClient.Credentials = credentialCache;
var reportStream = webClient.OpenRead(reportUrl);
using (MemoryStream memoryStream = new MemoryStream())
{
reportStream.CopyTo(memoryStream);
response.Content = new ByteArrayContent(memoryStream.ToArray()); //new StreamContent(reportStream);
response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/pdf");
//response.Content.Headers.ContentLength = reportStream.Length;
response.Content.Headers.ContentDisposition.FileName = "QualityReview.pdf";
response.StatusCode = HttpStatusCode.OK;
return response;
}
}
}
}
The service call:
/**
* Prints the quality review
*/
function printQualityReview() {
questAPIService.printQualityReview(reviewId)
.then(function (response) {
var outputFilename = vm.reviewee.lastName + ', ' + vm.reviewee.firstName + ' ' + $filter('date')(vm.review.reviewDate, 'MMddyyyy') + '.pdf';
var blob = new Blob([response.data], { type: 'application/pdf' });
saveAs(blob, outputFilename);
}, function (error) {
$log.error('Printing failed: ', error);
toastr.error('There was an error attempting to print the quality review.');
});
}
The trick was to make sure to return a byte array in the response content and set the response type as ArrayBuffer when calling the API method.