Here’s the complete solution covering all three integration points:
1. NAST Output Control Integration:
First, ensure your NAST configuration generates true PDF format:
- Transaction: NACE
- Application: PLM (or your custom app)
- Output Type: ZPLM
- Processing Routine: Must use function module that generates PDF
- Device Type: PDF1 (critical - not LP01 or other formats)
Verify the output program:
" In your NAST processing program
CALL FUNCTION 'CONVERT_OTF_TO_PDF'
EXPORTING
format = 'PDF'
IMPORTING
bin_filesize = lv_pdf_size
TABLES
otf = lt_otf_data
lines = lt_pdf_data.
2. OData Content-Type Configuration:
Create or extend the OData service’s DPC_EXT class. Override the GET_STREAM method:
METHOD /plmb/if_od_document_dpc~get_stream.
DATA: lv_document_id TYPE string,
lv_pdf_content TYPE xstring,
lv_mime_type TYPE string VALUE 'application/pdf',
ls_stream TYPE ty_s_media_resource.
" Get document ID from key
lv_document_id = it_key_tab[ name = 'DocumentId' ]-value.
" Retrieve PDF from NAST spool
CALL FUNCTION 'Z_GET_NAST_PDF_CONTENT'
EXPORTING
iv_document_id = lv_document_id
IMPORTING
ev_pdf_xstring = lv_pdf_content.
" Set response headers for PDF streaming
ls_stream-mime_type = lv_mime_type.
ls_stream-value = lv_pdf_content.
" Critical: Set Content-Type header explicitly
set_header(
EXPORTING
iv_name = 'Content-Type'
iv_value = lv_mime_type ).
set_header(
EXPORTING
iv_name = 'Content-Disposition'
iv_value = |inline; filename="{lv_document_id}.pdf"| ).
copy_data_to_ref(
EXPORTING
is_data = ls_stream
CHANGING
cr_data = er_stream ).
ENDMETHOD.
3. Fiori PDF Rendering Configuration:
Update your Fiori app’s manifest.json:
{
"sap.app": {
"dataSources": {
"mainService": {
"uri": "/sap/opu/odata/PLMB/OD_DOCUMENT_SRV/",
"type": "OData",
"settings": {
"odataVersion": "2.0",
"localUri": "localService/metadata.xml"
}
}
}
},
"sap.ui5": {
"resourceRoots": {
"pdfjs": "./lib/pdfjs"
}
}
}
In your controller, handle PDF rendering with proper content type:
onDisplayPDF: function(sDocumentId) {
var oModel = this.getView().getModel();
var sPath = "/DocumentSet('" + sDocumentId + "')/PDFContent";
// Read with proper headers
oModel.read(sPath, {
headers: {
"Accept": "application/pdf"
},
success: function(oData, response) {
var sContentType = response.headers["content-type"];
if (sContentType === "application/pdf") {
// Create blob URL for PDF viewer
var byteCharacters = atob(oData.value);
var byteNumbers = new Array(byteCharacters.length);
for (var i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
var blob = new Blob([byteArray], {type: "application/pdf"});
var url = URL.createObjectURL(blob);
// Display in PDF viewer
this.getView().byId("pdfViewer").setSource(url);
}
}.bind(this)
});
}
Testing Checklist:
- Test NAST output directly (transaction NAST) - should generate valid PDF
- Test OData service in Gateway Client (/IWFND/GW_CLIENT) - verify Content-Type header
- Test in browser network tab - response should show application/pdf
- Clear browser cache before testing Fiori app
The root cause is that PDF content requires explicit Content-Type handling at all three integration points. Missing any one will cause rendering failures.