Phidiax Tech Blog

Adventures in custom software and technology implementation.

SSRS: Stopping PDF Font Embedding ... Temporarily

SSRS and PDF Exports generally play nicely together to generate a quality printable document. If space is a problem when you start storing or processing the resulting PDFs, the first thing you'll find is that SSRS defaults to embedding fonts within the PDF documents produced. When you don't have control over the client printer and machine, this is ideal as it ensures that the client will end up seeing what you intended rather than an approximation using only the locally installed fonts.

In general if you use the Bing/Google machine to figure out how to turn this off, you'll get information about updating the PDF renderer configuration in the RSreportserver.config file with the following:

  <Configuration>
   <DeviceInfo>
      <EmbedFonts>None</EmbedFonts>
   </DeviceInfo>
  </Configuration>

The trouble here? That's universal to the server. So any PDFs where you don't want the fonts excluded have to go on another SSRS server (Just what we all want: to maintain double the number of SSRS installations... right?). 

SSRS Reporting Web Service

When you make calls to the SSRS Reporting Web Service, the render method can accept a parameter called "DeviceInfo." So instead of pasting the above information into the RSReportServer.config file, we can DIRECTLY pass this DeviceInfo XML as the DeviceInfo parameter. This means that the PDF will not embed fonts for this individual report service call, and will return the resulting PDF file as base-64 encoded bytes we can write out to our desired location, and since the fonts won't be embedded, they'll be a lot smaller.

SSRS Reporting Web Service Primer

For those not familiar with using the SSRS Web Services to render a report, the following will provide the necessary method calls to use to properly render a report without embedding PDFs. This will require three separate service calls to the ReportExecution2005.asmx service (http://SSRS-Server/ReportServer/ReportExecution2005.asmx):

  1. Call LoadReport, passing the report path: 
    <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:rep="http://schemas.microsoft.com/sqlserver/2005/06/30/reporting/reportingservices">
       <soap:Header>
          <rep:TrustedUserHeader>
          </rep:TrustedUserHeader>
       </soap:Header>
       <soap:Body>
          <rep:LoadReport>
             <rep:Report>/ReportFolder/ReportName</rep:Report>
          </rep:LoadReport>
       </soap:Body>
    </soap:Envelope>
    
    This will return an ExecutionHeader type object, which contains an ExecutionID of the "report session." This will be passed into the next two calls to maintain the loaded report.
  2. Call SetExecutionParameters, passing in the ExecutionHeader retrieved in step 1, and a list of the report parameter names and values:
    <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:rep="http://schemas.microsoft.com/sqlserver/2005/06/30/reporting/reportingservices">
       <soap:Header>
          <rep:TrustedUserHeader>
          </rep:TrustedUserHeader>
          <rep:ExecutionHeader>
             <rep:ExecutionID>EXECUTION_ID_STRING_FROM_STEP_1</rep:ExecutionID>
          </rep:ExecutionHeader>
       </soap:Header>
       <soap:Body>
          <rep:SetExecutionParameters>
             <rep:Parameters>
                <rep:ParameterValue>
                   <rep:Name>PARAMETER_NAME</rep:Name>
                   <rep:Value>PARAMETER_VALUE</rep:Value>
                </rep:ParameterValue>
                <rep:ParameterValue>
                   <rep:Name>PARAMETER_NAME_2</rep:Name>
                   <rep:Value>PARAMETER_VALUE_2</rep:Value>
                </rep:ParameterValue>
             </rep:Parameters>
          </rep:SetExecutionParameters>
       </soap:Body>
    </soap:Envelope>
    
  3. Call Render, passing in the ExecutionHeader, the format (PDF), and the XML above in the DeviceInfo parameter (note that the inner XML is "escaped" replacing the greater/less in the markup: this is to work in a test utility such as SoapUI. When using a proxy class in .NET, this is not necessary):
    <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:rep="http://schemas.microsoft.com/sqlserver/2005/06/30/reporting/reportingservices">
       <soap:Header>
          <rep:TrustedUserHeader>
          </rep:TrustedUserHeader>
          <rep:ExecutionHeader>
             <rep:ExecutionID>EXECUTION_ID_STRING_FROM_STEP_1</rep:ExecutionID>
          </rep:ExecutionHeader>
       </soap:Header>
       <soap:Body>
          <rep:Render>
             <rep:Format>PDF</rep:Format>
             <rep:DeviceInfo>
                &lt;DeviceInfo&gt;
                   &lt;EmbedFonts&gt;None&lt;/EmbedFonts&gt;
                &lt;/DeviceInfo&gt;
             </rep:DeviceInfo>
          </rep:Render>
       </soap:Body>
    </soap:Envelope>
    
    The return from the Render method will include base-64 encoded file in the RenderResponse.Result property. When written to disk, this will be the PDF file sans embedded fonts.



Loading

Privacy Policy  |  Contact  |  Careers

2009-2017 Phidiax, LLC - All Rights Reserved