-1

我使用 .NET 在我的 WEBAPI 控制器上执行此操作,该操作从 SSRS 报告链接返回字节:

     public IHttpActionResult GetReport(int? Id)
    {
        if (Id == null)
        {
            return NotFound();
        }

        var reportServer = ConfigurationManager.AppSettings["Report"];
        var reportPath = $"{reportServer}/myReport&Id={Id}&rs:Format=PDF";
        WebClient Client = new WebClient();
        Client.UseDefaultCredentials = true;
        byte[] reportBytes = Client.DownloadData(reportPath);

        var reportBase64 = Convert.ToBase64String(reportBytes);

        return Ok(reportBase64);
    }

当我尝试从这个返回生成 PDF 时,使用这个 react/redux 代码(我正在使用 axios)......

    //...code
    const reportBlob = new Blob([myReportData], { type: "application/pdf" });
    const reportBlobUrl = URL.createObjectURL(reportBlob);
    window.open(reportBlobUrl);   

.....它打开了一个带有 PDF 模板的新浏览器选项卡,但显示 PDF 错误为:“加载 PDF 文档失败”。

任何地方都没有回答者可以帮助我解决这个问题。:(

注意:“axios”调用它返回的字节数组与 WEBAPI 返回的字节数组相同,“myReportData”变量也是如此。

4

1 回答 1

1

所以我在4天后自己弄清楚了。任何需要此功能的人(在 c# 代码中以 PDF 格式呈现 SSRS 报告,从 ASP.NET WEB API 返回 PDF 字节,这是您必须在 webapi 控制器中执行的操作,以从要发送的报告查看器命名空间生成 PDF 字节使用 Redux 到您的 React 应用程序。

WEB API ASP.NET(使用 VS 2019 的 .NET Framework 4.6): 注意:我对第一个选项进行了评论,并且其工作方式与我更喜欢的选项 2 相同。

    // return type is Bytes
    [HttpGet]
    [Route("api/YourReport/{testId}")]
    public async Task<IHttpActionResult> GetYourReportAsync(int? testId)
    {
        if (testId == null)
        {
            return NotFound();
        }

        try
        {
            // 1. Works in this way without '?' on the end of the URL
            // URL should be like this: "http://-yourServerName-/reportserver/ReportExecution2005.asmx"

            //ReportExecutionService rs = new ReportExecutionService();
            //rs.Credentials = CredentialCache.DefaultCredentials;
            //rs.Url = "http://-yourServerNamein here-/reportserver/ReportExecution2005.asmx";

            //// Render arguments
            //byte[] result = null;
            //string reportPath = "/-yourReportsFolderName-/-yourReportName-";
            //string format = "PDF";
            //string historyID = null;
            //string devInfo = @"<DeviceInfo><Toolbar>False</Toolbar></DeviceInfo>";

            //// parameters
            //ParameterValue[] parameters = new ParameterValue[1];
            //parameters[0] = new ParameterValue();
            //parameters[0].Name = "yourId";
            //parameters[0].Value = testId.ToString();

            //string encoding;
            //string mimeType;
            //string extension;
            //Warning[] warnings = null;             
            //string[] streamIDs = null;
            //ExecutionInfo execInfo = new ExecutionInfo();
            //ExecutionHeader execHeader = new ExecutionHeader();

            //rs.ExecutionHeaderValue = execHeader;

            //execInfo = rs.LoadReport(reportPath, historyID);

            //rs.SetExecutionParameters(parameters, "en-us");
            //string SessionId = rs.ExecutionHeaderValue.ExecutionID;

            //try
            //{
            //// result type is bytes
            //    result = rs.Render(format, devInfo, out extension, out encoding, out mimeType, out warnings, out streamIDs);                  

            //}
            //catch (SoapException)
            //{
            //    throw;
            //}  
            //// below, just in case that you want to save it locally in PDF format.            
            //try
            //{
            //    FileStream stream = File.Create(@"c:\report.pdf", result.Length);
            //    
            //    stream.Write(result, 0, result.Length);
            //    Console.WriteLine("Result written to the file.");
            //    stream.Close();
            //}
            //catch (Exception)
            //{
            //    throw;
            //}

            //return await Task.Run(() => Ok(result));

            // 2. Works this way also with '?' on the end of the URL
            // URL should be like this: "http://-yourServerName-/reportserver/ReportExecution2005.asmx?"

            using (ReportViewer yourReportViewer = new ReportViewer())
            {
                yourReportViewer.ProcessingMode = ProcessingMode.Remote;

                // get the values from your web.config. 
                yourReportViewer.ServerReport.ReportServerUrl = new Uri(ConfigurationManager.AppSettings["youtReport"]);
                yourReportViewer.ServerReport.ReportPath = $"/yourReportsFolder/yourReport";
                ;
                ReportParameter testPlanIdParameter = new ReportParameter();
                testPlanIdParameter.Name = "yourId";
                testPlanIdParameter.Values.Add(testId.ToString());

                yourReportViewer.ServerReport.SetParameters(new ReportParameter[] { testIdParameter });

                byte[] yourReportBytes = yourReportViewer.ServerReport.Render("PDF");

                return await Task.Run(() => Ok(yourReportBytes));
            }
        }
        catch (SoapException)
        {
            throw;
        }
        catch (Exception)
        {
            throw ;
        }
    }

REACT/REDUX n强文本注释:您必须将从您的 WEB API 控制器返回的字节流转换为 BLOB 格式,以便在 PDF 格式/类型的新棕色选项卡中呈现它。

一种。按钮动作/行为

               <div className="btn-group-vertical" role="group">

                        <button className="btn btn-sm btn-success ml-2 mb-2" style={{ width: '160px' }} onClick={(e) => openReport(e, testId)}>
                            <i className="fas fa-print"></i>&nbsp;&nbsp;
                                Report
                     </button>       
                </div>

湾。组件(我省略了 redux 部分(reducers、actions、apiservice...)

openReport(event, item) {
    event.preventDefault();
    this.props.actions.loadReport(item);
    this.setState({ Report: this.props.Report });
    const ReportData = this.state.Report;

    const b64toBlob = (b64Data, contentType = '', sliceSize = 512) => {
        const byteCharacters = atob(b64Data);
        const byteArrays = [];

        for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
            const slice = byteCharacters.slice(offset, offset + sliceSize);

            const byteNumbers = new Array(slice.length);
            for (let i = 0; i < slice.length; i++) {
                byteNumbers[i] = slice.charCodeAt(i);
            }

            const byteArray = new Uint8Array(byteNumbers);
            byteArrays.push(byteArray);
        }

        const blob = new Blob(byteArrays, { type: contentType });
        return blob;
    }
    const ReportBlob = b64toBlob(ReportData, 'application/pdf');

    const ReportBlobUrl = URL.createObjectURL(ReportBlob);
    window.open(ReportBlobUrl);

}
于 2019-12-09T20:07:31.980 回答