PDF.JS not working on 3.1.1-4

Hello All,

Last week I finished my upgrade of OJS from 2.4.7-1 to 3.0.2 and then to 3.1.1-4
(2.4.7-1 to 3.1.1-4 didn’t work).

While most things seem to be ok, When I click the articles PDFs the file is
downloaded instead of viewed.

This is what I did:

  • I’ve already checked and the PDF.JS PDF Viewer and HTML Article Galley
    plugins are enabled. Chrome console gives the following error:

GridHandler.js:371 Uncaught Error: Row with id tinymceplugin not found!
at proxyConstructor.$.pkp.controllers.grid.GridHandler.resequenceRows (GridHandler.js:371)
at proxyConstructor.$.pkp.controllers.grid.GridHandler.replaceElementResponseHandler (GridHandler.js:763)
at Object.success (Handler.js:304)
at fire (jquery.js:3099)
at Object.fireWith [as resolveWith] (jquery.js:3211)
at done (jquery.js:9310)
at XMLHttpRequest.callback (jquery.js:9720)

When I enabled the plugins, but the settings where saved.

  • Apache’s error_log shows no errors.
  • The files folder and it’s content permissions are 777.
  • The cache and public folders permissions are 777.
  • Tried even changing the whole ojs folder permissions to 777.
  • Using Chrome console, when the PDF is clicked it shows the message “Resource interpreted as Document
    but transferred with MIME type application/pdf”
  • Tested after upgraded to 3.0.2. It didn’t work.
  • Tried using both enable_cdn On and Off
  • Tried using both force_ssl On and Off

One very strange thing I’ve noticed is that pdf.js is not included in the page
source code. This can be seen here:


I’ve already searched the forum, but none of the posts I’ve found helped

Any suggestions? What am I missing here?



Hi @Oberdan

Were there any errors during upgrades?

If the plugin is enabled, I suspect OJS isn’t recognizing those files as PDFs here: https://github.com/pkp/pdfJsViewer/blob/master/PdfJsViewerPlugin.inc.php#L68

What file_type for those galleys is pointed inside database, submission_files table. E.g., SELECT * FROM submission_files WHERE submission_id = 11987 AND assoc_id = 7966

Hello @Vitaliy

There were some errors related to missing files, but other than that both upgrades ran fine. The file_type returned for that query is application/pdf. It seems that the file types are correct.

Running an SELECT file_type , COUNT(1) FROM submission_files GROUP BY file_type ORDER BY 2 DESC shows that all file_types are set.

I still think that the problem is related to pdf.js not being loaded. How do I know it is running?



I’d also check the integrity of the plugin’s code. Whether it corresponds (identical) to the actual one for this release.

The code can be debugged as usual in PHP with the output into the error log.

E.g., write something into the log with error_log() method just after this check. If this won’t appear in the logs, then the plugin is not enabled.

All inside this method will be executed on every articles’ PDF galley page, you can check it the same way. To write variables into the logs.

I’ve checked the plugin code and it’s identical to the one inside ojs-3.1.1-4.tar.gz.

Added error_log('TEST - PDF.JS is enabled'); after $this->getEnabled($mainContextId) and the message showed on error_log, so the plugin is enabled.

Tried adding something similar inside articleCallback and it didn’t show on error_log. So I guess the problem is here…



You checked the last one with visiting PDF galley page, right? e.g. https://portal.biblioteca.unesp.br/ojs3/index.php/bolema/article/view/11987/7966

I’m asking because after accessing this page the PDF downloads and it means that articleCallback methods works but maybe not fully.

This method injects the code inside a hook. The purpose of this method is rendering PDF galleys on a separate page, e.g., this line displays a Smarty template when user goes by PDF’s link. But that part is wrapped inside if condition, and I suspect that code execution stops there. Can you double check if this is true?

Another thing is that the hook is here: https://github.com/pkp/ojs/blob/master/pages/article/ArticleHandler.inc.php#L202
and I have no idea what can be wrong there except the conflict with some other plugin that uses this hook too. If you haven’t got any old code there, this should not happen.


I can certainly say that the problem is not with PDF.js as I’m able to embed your PDF galley file inside it manually: https://portal.biblioteca.unesp.br/ojs3/plugins/generic/pdfJsViewer/pdf.js/web/viewer.html?file=https://portal.biblioteca.unesp.br/ojs3/index.php/bolema/article/download/11987/7966

So, most probable reason is that $galley->getFileType() inside articleCallback method returns not expected value. You can check it by described above method.

Actually, I know that @ajnyga made a lot of upgrades from OJS 2+. Maybe he encountered with such problems.

The link is indeed working. About the previous message:

Yes, I checked the last one with visiting PDF galley page.

About the hook, my code inside PDF.js register method is:

    if ($this->getEnabled($mainContextId)) {
            error_log('TEST - PDF.JS is enabled');
            HookRegistry::register('ArticleHandler::view::galley', array($this, 'articleCallback'));
            error_log('TEST - PDF.JS articleCallback hook');
            HookRegistry::register('IssueHandler::view::galley', array($this, 'issueCallback'));
            error_log('TEST - PDF.JS issueCallback hook');

And all three messages are displayed in my log.

About articleCallback, I have this:

        function articleCallback($hookName, $args) {
                $request =& $args[0];
                $issue =& $args[1];
                $galley =& $args[2];
                $article =& $args[3];

                error_log('TEST - articleCallback test method');

                $templateMgr = TemplateManager::getManager($request);
                if ($galley && $galley->getFileType() == 'application/pdf') {
                        $application = Application::getApplication();
                                'pluginTemplatePath' => $this->getTemplatePath(),
                                'pluginUrl' => $request->getBaseUrl() . '/' . $this->getPluginPath(),
                                'galleyFile' => $galley->getFile(),
                                'issue' => $issue,
                                'article' => $article,
                                'galley' => $galley,
                                'jQueryUrl' => $this->_getJQueryUrl($request),
                                'currentVersionString' => $application->getCurrentVersion()->getVersionString(false),
                        $templateMgr->display($this->getTemplatePath() . '/articleGalley.tpl');
                        return true;

                return false;

As the message does not show in the log file, I assume this method is never called.

I’m even checking if Html Article Galley is enabled, here is the message in the register method:

                        if ($this->getEnabled($mainContextId)) {
                                error_log('TEST - Article Galley emabled');
                                HookRegistry::register('ArticleHandler::view::galley', array($this, 'articleViewCallback'), HOOK_SEQUENCE_LATE);
                                HookRegistry::register('ArticleHandler::download', array($this, 'articleDownloadCallback'), HOOK_SEQUENCE_LATE);

That also show in the log.

The only other plugin that uses an articleCallback method is lens Galley, that is disabled. I’ve tried even deleting the plugin.

I removed some other plugins using references to ArticleHandler, but it didn’t work. Do you want me to download the source from GitHub, copy my public folder and config.inc.php from the current install and try again?



I had this too, I think the problem was permissions related as I recall, the server didnt have permissions to write pdf files and therefore they weren’t being returned so the web dev tools showed me a blank response.

Hope it helps,

Sorry, does not look familiar.

The only reason why articleCallback is not being called I can think of right now is that something else is calling the ArticleHandler::view::galley hook before the plugin has the opportunity. But if that is already checked, then I do not know.

Hmm, as I remember I saw similar problem on several OJS 3+ sites upgraded from OJS 2, but I never have had an opportunity to discuss this problem with them.

Exploring the response on pdf viewing request I noticed that it has status code 302. In this case browser uses Location directive in the response headers, which is e.g.: .../ojs3/index.php/bolema/article/download/.... The response body is empty and it should contain Smarty template for galley page.

Internet search indicates that the problem might by inside apache Virtual Host directives. @Oberdan, can you check if they contain only necessary and correct data. Also, I would thoroughly check OJS config file.

This particular install is not inside a virtualhost, it is just a folder inside the default apache htdocs. I’ll create a virtualhost just like we use for our production version. I’ll let you know if that works.

There is only need to check whether there are not any rewrite rules from apache. If it’s default configuration, we can exclude that problem.

Thus, can you return to the articleCallback method and check what returns $galley->getFileType()? You can write it into the log just after this line.

Edit: Ah sorry, didn’t see that you wrote that this method is never called…

tagging @asmecher because I’ve run out of ideas.

Well, tested it inside a virtualhost like this:

<VirtualHost *:80>
    ServerName ojs-teste.biblioteca.unesp.br
    ServerAdmin oberdan.luiz@unesp.br

    DocumentRoot "/ojs_temp/rc-3.1.1"

    <Directory /ojs_temp/rc-3.1.1>
      Options ExecCGI FollowSymLinks MultiViews
      AddDefaultCharset utf8
      AllowOverride AuthConfig Options FileInfo
      php_value default_charset "utf-8"
      php_value output_buffering On
      php_value session.auto_start 0
      php_value error_reporting 6131
      php_value memory_limit 64M
      Require all granted
      RewriteEngine on

    ErrorLog ${APACHE_LOG_DIR}/ojs_teste_error.log
    CustomLog ${APACHE_LOG_DIR}/ojs_teste_access.log combined

And it didn’t work.

Hi @Oberdan,

Can you check whether there is an entry for this plugin in the versions table? It should be something like…

 mysql> select * from versions where product like '%pdfjs%';
| major | minor | revision | build | date_installed      | current | product_type    | product     | product_class_name | lazy_load | sitewide |
|     1 |     0 |        0 |     0 | 2018-10-24 17:51:09 |       1 | plugins.generic | pdfJsViewer | PdfJsViewerPlugin  |         1 |        0 |
1 row in set (0.00 sec)

Alec Smecher
Public Knowledge Project Team

Hi @asmecher,

Yes, there is an entry. The only difference is the date_installed, that is older (2015-04-15 10:26:35):




Hi @Oberdan,

Is there any customization in that installation, or a chance that you might have mixed OJS 2.x code together with your OJS 3.x installation? For example, I’m wondering whether you might also have a copy of the Google Viewer plugin (plugins/generic/googleViewer) accidentally included in your OJS 3.x codebase.

Alec Smecher
Public Knowledge Project Team

Hello, @asmecher,

No, there is no OJS 2.x code mixed, and no googleViewer. It’s just the 3.1.1-4 code right now.



Hi @Oberdan,

OK, thanks. It’s possible that your error_log calls are being invoked when you’re in e.g. the plugin administration area, but not when the plugin is being used; can you try viewing an article and check your logs to see that it’s this invocation that you’re seeing recorded, rather than exploration of the plugin administration area?

(This would happen e.g. if the plugin was installed in the wrong directory or something like that was preventing registration from happening normally.)

Alec Smecher
Public Knowledge Project Team

Hi @asmecher,

Tested going from the first page to one article and my error_log shows this:

[Wed Oct 31 12:40:13.176819 2018] [:error] [pid 549] [client] TEST - PDF.JS is enabled
[Wed Oct 31 12:40:13.176919 2018] [:error] [pid 549] [client] TEST - PDF.JS articleCallback set
[Wed Oct 31 12:40:13.178118 2018] [:error] [pid 549] [client] TEST - ARTICLE GALLEY enabled
[Wed Oct 31 12:40:13.879268 2018] [:error] [pid 549] [client] TEST - PDF.JS is enabled, referer: http://ojs-teste.biblioteca.unesp.br/
[Wed Oct 31 12:40:13.879330 2018] [:error] [pid 549] [client] TEST - PDF.JS articleCallback set, referer: http://ojs-teste.biblioteca.unesp.br/
[Wed Oct 31 12:40:13.880338 2018] [:error] [pid 549] [client] TEST - ARTICLE GALLEY enabled, referer: http://ojs-teste.biblioteca.unesp.br/
[Wed Oct 31 12:40:23.844996 2018] [autoindex:error] [pid 557] [client] AH01276: Cannot serve directory /ojs_temp/rc-3.1.1/public/journals/7/: No matching DirectoryIndex (index.html,index.cgi,index.pl,index.php,index.xhtml,index.htm) found, and server-generated directory index forbidden by Options directive, referer: http://ojs-teste.biblioteca.unesp.br/index.php/bolema/issue/view/1050
[Wed Oct 31 12:40:32.645785 2018] [:error] [pid 330] [client] TEST - ARTICLE HANDLER view called, referer: http://ojs-teste.biblioteca.unesp.br/index.php/bolema/issue/view/1050
[Wed Oct 31 12:40:32.655902 2018] [:error] [pid 330] [client] TEST - ARTICLE HANDLER $galleys is true, referer: http://ojs-teste.biblioteca.unesp.br/index.php/bolema/issue/view/1050
[Wed Oct 31 12:40:32.702007 2018] [:error] [pid 330] [client] TEST - ARTICLE HANDLER download, referer: http://ojs-teste.biblioteca.unesp.br/index.php/bolema/issue/view/1050

I’ve added some more error_log calls inside pages/article/ArticleHandler.inc.php:

                        'issue' => $issue,
                        'article' => $article,
                        'fileId' => $fileId,

                error_log('TEST - ARTICLE HANDLER view called');

                if (!$this->userCanViewGalley($request, $articleId, $galleyId)) fatalError('Cannot view galley.');

                // Get galleys sorted into primary and supplementary groups
                $galleys = $article->getGalleys();
                $primaryGalleys = array();
                $supplementaryGalleys = array();
                if ($galleys) {
                        error_log('TEST - ARTICLE HANDLER $galleys is true');


                if (!$galley) {
                        // No galley: Prepare the article landing page.

                        error_log('TEST - ARTICLE HANDLER $galley is false');
                        // Get the subscription status if displaying the abstract;
                        // if access is open, we can display links to the full text.

                        // The issue may not exist, if this is an editorial user
                        // and scheduling hasn't been completed yet for the article.
                        $issueAction = new IssueAction();
                        $subscriptionRequired = false;
                        if ($issue) {
                                $subscriptionRequired = $issueAction->subscriptionRequired($issue, $journal);

                        $subscribedUser = $issueAction->subscribedUser($user, $journal, isset($issue) ? $issue->getId() : null, isset($article) ? $article->getId() : null);
                        $subscribedDomain = $issueAction->subscribedDomain($request, $journal, isset($issue) ? $issue->getId() : null, isset($article) ? $article->getId() : null);

                        $templateMgr->assign('hasAccess', !$subscriptionRequired || (isset($article) && $article->getAccessStatus() == ARTICLE_ACCESS_OPEN) || $subscribedUser || $subscribedDomain);

                        $paymentManager = Application::getPaymentManager($journal);
                        if ( $paymentManager->onlyPdfEnabled() ) {
                                $templateMgr->assign('restrictOnlyPdf', true);
                        if ( $paymentManager->purchaseArticleEnabled() ) {
                                $templateMgr->assign('purchaseArticleEnabled', true);

                        if (!HookRegistry::call('ArticleHandler::view', array(&$request, &$issue, &$article))) {
                                return $templateMgr->display('frontend/pages/article.tpl');
                } else {
                        // Galley: Prepare the galley file download.
                        error_log('TEST - ARTICLE HANDLER download');
                        if (!HookRegistry::call('ArticleHandler::view::galley', array(&$request, &$issue, &$galley, &$article))) {
                                $request->redirect(null, null, 'download', array($articleId, $galleyId));