I have implemented a feature for PDF conversion using an external java program based on iText (performance is not an issue, the system is for internal usage only, users are less than a hundred, concurrent connections less than ten and daily PDF conversions just a handfull or two). I get the HTML from an element on my page, I append all CSS rules and send the standalone HTML so obtained to the server using a dynamically generated form:
$('#convert-to-pdf-link').click(function() {
let inner = '<html><head><title>' + document.title + '</title>' ;
let rules_text = '' ;
[...document.styleSheets].forEach(function(sheet) {
let rules = [ ... (sheet.cssRules || sheet.rules) ] ;
rules.forEach(function(rule) {
rules_text += rule.cssText + "\n" ;
}) ;
}) ;
inner += `<style>${rules_text}</style>` ;
inner += '</head><body >' ;
let contents = $('.node--type-mytype').html() ;
inner += contents ;
inner += '</body></html>' ;
let form = document.querySelector('form[action="/ls/topdf"]') ;
if (form === null) {
form = document.createElement('form') ;
form.setAttribute('action', '/ls/topdf') ;
form.setAttribute('method', 'post') ;
document.body.append(form) ;
}
let input_el = form.querySelector('input[name="input_file"]') ;
if (input_el === null) {
input_el = document.createElement('input') ;
input_el.setAttribute('type', 'text') ;
input_el.setAttribute('name', 'input_file') ;
input_el.classList.add('hidden') ;
form.append(input_el) ;
}
input_el.value = inner ;
form.submit() ;
return false ;
}) ;
The controller gets the html from the form, saves it to file, runs the conversion program, and returns the resulting PDF in a BinaryFileResponse
:
class UtilitiesController extends ControllerBase {
[...]
public function convertToPdf(Request $request) {
$scheme = \Drupal::config('system.file')->get('default_scheme') ;
$dirname = "$scheme://appoggio" ;
$filesystem = \Drupal::service('file_system') ;
$filesystem->prepareDirectory($dirname,
FileSystemInterface::CREATE_DIRECTORY|FileSystemInterface::CREATE_DIRECTORY) ;
$basename = time() ;
$input_uri = "$dirname/$basename.html" ;
$body = $request->request->get('input_file') ;
$infile = file_save_data($body, $input_uri, $replace=FileSystemInterface::EXISTS_REPLACE) ;
$inpath = $filesystem->realpath($input_uri) ;
$pdf_uri = "$dirname/$basename.pdf" ;
$pdfpath = $filesystem->realpath($pdf_uri) ;
$command = "java -jar /opt/TestConvHtml2Pdf_jar/TestConvHtml2Pdf.jar '$inpath' '$pdfpath'" ;
exec($command, $output, $retval) ;
if ($retval === 0) {
$response = new BinaryFileResponse($pdf_uri, 200, ['Content-Type' => 'application/pdf']) ;
$response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT, "$basename.pdf") ;
return $response ;
}
else {
$this->log->error("odg_to_pdf() failed with error code $retval. Details:<br>" .
implode('<br>', $output)) ;
foreach ($output as $line)
$rows[] = [ $line ] ;
return [
'#theme' => 'table',
'#header' => [ "Errore nella conversione in PDF: $retval" ],
'#rows' => $rows,
] ;
}
}
}
Everything works nicely, but only if I keep the route to the controller open, i.e., in mymodule.routing.yml
,
mymodule.to_pdf:
path: '/ls/topdf'
defaults:
_controller: '\Drupal\mymodule\Controller\UtilitiesController::convertToPdf'
methods: [POST]
options:
no_cache: 'TRUE'
requirements:
_access: 'TRUE'
If I replace _access: 'TRUE'
with _role: 'authenticated'
, I get a 403, in spite of the fact that the session cookie is present in the request. I tried to spot other differences in the headers of the request for conversion and of other requests, but I couldn't find any.
What am I missing?
_permission
rather than a_role
._user_is_logged_in: 'TRUE'
underrequirements
_permission
worked while the_role
didn't?