使用React/Redux从ASP.NET WEB API获取要以PDF格式呈现的字节数组

使用React/Redux从ASP.NET WEB API获取要以PDF格式呈现的字节数组,pdf,asp.net-web-api,react-redux,Pdf,Asp.net Web Api,React Redux,我使用从SSRS报告链接返回字节的.NET在WEBAPI的控制器上执行此操作: public IHttpActionResult GetReport(int? Id) { if (Id == null) { return NotFound(); } var reportServer = ConfigurationManager.AppSettings["Report"];

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

     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);
    }
当我尝试使用这个react/redux代码从这个返回生成PDF时(我使用的是axios)

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

任何地方都没有人能帮我解决这个问题(


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

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

WEB API ASP.NET(.NET Framework 4.6使用VS 2019): 注意:第一个选项与我更喜欢的选项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 ;
        }
    }
//返回类型为字节
[HttpGet]
[路由(“api/YourReport/{testId}”)]
公共异步任务GetYourReportAsync(int?testId)
{
if(testId==null)
{
返回NotFound();
}
尝试
{
//1.以这种方式工作,URL末尾不带“?”
//URL应如下所示:http://-yourServerName-/reportserver/ReportExecution2005.asmx"
//ReportExecutionService rs=新的ReportExecutionService();
//rs.Credentials=CredentialCache.DefaultCredentials;
//rs.Url=”http://-yourServerNamein 此处-/reportserver/ReportExecution2005.asmx”;
////渲染参数
//字节[]结果=空;
//string reportPath=“/-yourReportsFolderName-/-yourReportName-”;
//string format=“PDF”;
//字符串historyID=null;
//字符串devInfo=@“False”;
////参数
//ParameterValue[]参数=新参数值[1];
//参数[0]=新参数值();
//参数[0]。Name=“yourId”;
//参数[0]。值=testId.ToString();
//字符串编码;
//字符串模拟类型;
//字符串扩展;
//警告[]警告=null;
//字符串[]streamIDs=null;
//ExecutionInfo ExecutionInfo=新的ExecutionInfo();
//ExecutionHeader ExecutionHeader=新的ExecutionHeader();
//rs.ExecutionHeaderValue=ExecutionHeader;
//execInfo=rs.LoadReport(reportPath,historyID);
//rs.SetExecutionParameters(参数“en-us”);
//字符串SessionId=rs.ExecutionHeaderValue.ExecutionID;
//试一试
//{
////结果类型为字节
//结果=rs.Render(格式、devInfo、输出扩展、输出编码、输出mimeType、输出警告、输出streamid);
//}
//捕获(SoapException)
//{
//投掷;
//}  
////下面,以防您希望以PDF格式在本地保存它。
//试一试
//{
//FileStream stream=File.Create(@“c:\report.pdf”,result.Length);
//    
//stream.Write(result,0,result.Length);
//WriteLine(“结果写入文件”);
//stream.Close();
//}
//捕获(例外)
//{
//投掷;
//}
//返回等待任务。运行(()=>Ok(结果));
//2.以这种方式与URL末尾的“?”一起使用
//URL应如下所示:http://-yourServerName-/reportserver/ReportExecution2005.asmx?"
使用(ReportViewer yourReportViewer=new ReportViewer())
{
yourReportViewer.ProcessingMode=ProcessingMode.Remote;
//从web.config获取值。
yourReportViewer.ServerReport.ReportServerUrl=新Uri(ConfigurationManager.AppSettings[“youtReport”]);
yourReportViewer.ServerReport.ReportPath=$“/yourReportsFolder/yourReport”;
;
ReportParameter testPlanIdParameter=新的ReportParameter();
testPlanIdParameter.Name=“yourId”;
testPlanIdParameter.Values.Add(testId.ToString());
yourReportViewer.ServerReport.SetParameters(新的ReportParameter[]{TestedParameter});
byte[]yourReportBytes=yourReportViewer.ServerReport.Render(“PDF”);
返回等待任务。运行(()=>Ok(yourReportBytes));
}
}
捕获(SoapException)
{
投
}
捕获(例外)
{
投
}
}
REACT/REDUX nstrong text注意:您必须将从WEB API控制器返回的字节流转换为BLOB格式,以PDF格式/类型在新的brownser选项卡中呈现

a、 按钮的动作/行为

               <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>

openReport(e,testId)}>
汇报
b、 组件(我省略了redux部分(减速机、操作、apiservice…)

openReport(事件、项目){
event.preventDefault();
this.props.actions.loadReport(项目);
this.setState({Report:this.props.Report});
const ReportData=this.state.Report;
const b64toBlob=(b64Data,contentType='',sliceSize=512)=>{
常量ByTechCharacters=atob(B64数据);
常量字节数组=[];
for(让offset=0;offset               <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>
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);

}