Pdf.js: Случайное / явное выделение жирным шрифтом / искажение

Созданный на 31 мар. 2016  ·  46Комментарии  ·  Источник: mozilla/pdf.js

Ссылка на файл PDF:
default.pdf

Конфигурация:

  • Веб-браузер и его версия: версия 49.0.2623.87 (64-разрядная) [проблема не связана с браузером]
  • Операционная система и ее версия: Linux Ubuntu 15.10 [не зависит от ОС]
  • Версия PDF.js: [все / 1.3.91]
  • Расширение: pdf.js, встроенное в приложение

Шаги по воспроизведению проблемы:

  1. Многократно открывать вьювер
  2. Иногда отображение в порядке, иногда случайное выделение жирным шрифтом
  3. Частота кажется случайной
  4. Это ПРИЧИНА, установив "PDFJS.disableWorker = true;" (устранение этой проблемы с исправлениями)
  5. Я не могу "не" отключить воркера из-за массовой загрузки, которую он вызывает в _every_ view
  6. Контент загружается из строки в памяти
  7. Я проверил, что содержимое строки согласовано между Ok и поврежденными представлениями
  8. В многостраничных документах перемещение вперед на страницу, а затем назад всегда решает проблему.

Какое ожидаемое поведение? (добавить скриншот)
ok

Что пошло не так? (добавить скриншот)
corrupt

1-other 4-chrome-specific

Все 46 Комментарий

Я не могу "не" отключить воркер из-за массовой загрузки, которая вызывается при каждом просмотре.

Не могли бы вы объяснить эту часть?

Если вы пытаетесь использовать getDocument несколько раз, используйте один экземпляр PDFWorker. Трудно сказать, что вызывает повреждение шрифтов, но ссылка на рабочий пример может пролить свет. Можете ли вы создать / опубликовать пример, вызывающий проблему?

Хорошо, я не могу легко опубликовать ссылку. Если я работаю с включенными воркерами, он работает на 100%. Если я установлю флаг отключения, вы увидите проблему, показанную выше, случайным образом, может быть, 1 экземпляр из 4.

Я ограничился ответом «просто включите рабочих», подробно объяснив, «почему» я отключаю рабочего, а именно, что я довольно быстро отображаю множество небольших PDF-файлов, и добавляю 1,2 Мб для загрузки pdf_worker.js для каждый дисплей не практичен. Я просматривал код веб-воркера, чтобы узнать, есть ли у воркеров возможность кэшировать вызываемый ими скрипт .js, но мне ничего не удалось найти.

Мое первоначальное предположение (основанное на эффекте) заключается в том, что где-то есть что-то с глобальной областью действия, которое очищается правильно, если сценарий загружается для каждого экземпляра, что вызывает проблему, если сценарий рабочего процесса многократно используется повторно. Однако (!) Учитывая, что проблема может возникнуть на ПЕРВОМ отображении pdf, я немного не понимаю, на что смотреть.

Я ограничился ответом «просто включите рабочих», подробно объяснив, «почему» я отключаю рабочего, а именно, что я довольно быстро отображаю множество небольших PDF-файлов, и добавляю 1,2 Мб для загрузки pdf_worker.js для каждый дисплей не практичен.

@oddjobz Я все еще не понимаю, о чем

Не уверен, что проблема решена без кода для вашего решения, по умолчанию PDF.js кэширует код веб-работника при использовании на стандартном веб-сервере со стандартным браузером (в конфигурациях по умолчанию).

Ну, я не знаю, в чем разница между кодом, который я использую, и кодом, который у вас есть, но где-то разница есть. Во-первых, при отключенном работнике pdf_worker.js загружается один раз при первом обращении «только». При включенных рабочих процессах код загружается в каждый новый документ, и, похоже, ничего, что я делаю, не влияет на кеширование. (т.е. он не кешируется). Я подозреваю, что из-за того, что у разработчиков Chrome были проблемы с веб-рабочими и кешированным кодом, они отключили кеширование. Насколько я могу судить, все мои заголовки такие, какими должны быть для кеширования, но кеширования не происходит. (в то время как другие вещи хранятся в кэше)

У меня есть три важных бита;
а. Основной блок кода с тегом скрипта
б. Onload, который устанавливает глобальные переменные
c. Автономный класс, который отображает PDF в формате DIV

основной кодовый блок;

<script type="text/javascript" src="js/compatibility.js"></script>
<script type="text/javascript" src="js/pdf.js"></script>

код загрузки;

    PDFJS.disableWorker = true;
    PDFJS.verbosity = PDFJS.VERBOSITY_LEVELS.debug;
    PDFJS.workerSrc = "/js/pdf.worker.js";

определение класса;

JS.require('JS.Class',function(Class) {

    CLASS.PDFViewer = new Class({

        locked  : false,
        page        : 0,
        pages   : 0,
        pdf     : null,
        doc_id  : null,

        initialize: function(prefix) {
            this.canvas   = prefix+'-canvas';           // Canvas element ID we'll be rendering to
            this.prefix   = prefix;
            this.id_page  = '#'+this.canvas+'-page';    // Ident of page number
            this.id_pages = '#'+this.canvas+'-pages';   // Ident of page count
            this.setfocus(null);                        // Element to focus after render
        },
        reset:      function() { this.now_showing = null; console.log("PDF Reset")},
        set:        function(doc_id) { this.doc_id = doc_id; console.log("Docid:",doc_id) },
        load:       function() { this.fetch(this.doc_id); },
        set_doc:    function() {},
        setfocus: function(field_id) { this.focuson = field_id; },

        decode: function(base64) {
            var raw = atob(base64);
            var uint8Array = new Uint8Array(raw.length);
            for (var i = 0; i < raw.length; i++) {
                uint8Array[i] = raw.charCodeAt(i);
                }
          return uint8Array;
        },

        full_screen: function() {
            if( $('#'+this.prefix+'-hide-me').is(':visible') ) {
                $('#'+this.prefix+'-hide-me').hide();
                $('#'+this.prefix+'-full-screen').removeClass("col-sm-7");
                $('#'+this.prefix+'-full-screen').addClass("col-sm-12");
            } else {
                $('#'+this.prefix+'-hide-me').show();
                $('#'+this.prefix+'-full-screen').removeClass("col-sm-12");
                $('#'+this.prefix+'-full-screen').addClass("col-sm-7");
            }
            this.turn_page();
        },
        focus: function() {
            if(this.focuson) {
                console.log("SetFocus>>",this.focuson);
                setTimeout("$('"+this.focuson+"').focus()",100);
                this.focuson = null;
            }
        },
        display: function(pdf) {
            this.pdf = pdf;
            $(this.id_pages).text(this.pdf.numPages);
            this.pages = this.pdf.numPages;
            this.page = 1;
            this.turn_page();
        },
        fetch: function(rid) {
            if(this.locked) return false;
            var self = this;
            var src = '/images/default.pdf';
            function success(data) {
                if(!LIB.check_error(data)) return false;
                if(data.pdf) src = self.decode(data.pdf);
                self.locked = true;
                PDFJS.getDocument(src).then(function(pdf){ self.display(pdf); });
                return true;
            }
            ionman.call('nac.rpc.pdf_spec',{'rid': rid},success)
            return true;
        },
        turn_page: function() {
        var self = this;
            self.pdf.getPage(self.page).then(function(page) {
                var canvas = document.getElementById(self.canvas);
        var ctx = canvas.getContext('2d');
        var unscaledViewport = page.getViewport(1.0);
                canvas.width = $('#'+self.canvas).width();
                var scale = canvas.width / unscaledViewport.width;
                var viewport = page.getViewport(scale);
                canvas.height = viewport.height;
            var renderContext = { canvasContext: ctx, viewport: viewport };
        page.render(renderContext).promise.then(function(){
                setTimeout(function(){
                    self.locked = false;
                        self.focus();
                    },250);
                });
                $(self.id_page).text(self.page);
            });
        },
        next: function() {
            if( this.page == this.pages) return;
            this.page += 1;
            this.turn_page();
        },
        prev: function() {
            if( this.page == 1) return;
            this.page -= 1;
            this.turn_page();
        }
    });

Так и делаю;

var viewer = CLASS.PDFViewer('pdf');
viewer.fetch();

И я получаю документ по умолчанию - это DIV с идентификатором «pdf-canvas».

Попробуем это:

  1. Откройте http://mozilla.github.io/pdf.js/web/viewer.html в Chrome.
  2. Откройте инструменты разработчика на странице «Сеть» и покажите разделенную консоль (нажмите «esc» на этой вкладке).
  3. Убедитесь, что он не попал в исключение (в противном случае отключите прерывание исключения и обновите)
  4. Убедитесь, что параметр «Отключить кеш» отключен (в противном случае снимите флажок и обновите)
  5. В консоли выполните PDFJS.getDocument('http://mozilla.github.io/pdf.js/web/compressed.tracemonkey-pldi-09.pdf')
  6. Обратите внимание, что второй "pdf.worker.js" имеет статус "200 OK (из кеша)"

screen shot 2016-03-31 at 10 51 26 am

Фрагменты кода бесполезны. Разверните где-нибудь небольшой пример (например, на страницах github)

Да, я вижу ... это, похоже, более новая версия PDF.js, чем я использую ... если разница не в проблеме, я сравню заголовки Varnish с моим веб-сервером, чтобы увидеть, Я могу понять, почему он не кешируется.

Я скорее подозреваю, что из-за того, что у разработчиков Chrome были проблемы с веб-рабочими и кешированным кодом, они отключили кеширование.

Я не вижу связи между этим и опцией disableWorker. Запрашивается pdf.worker.js независимо от того, истинно оно или ложно. Так что проблема не должна иметь отношения к кешированию.

Для простоты я предполагаю, что это связано с тем, как обмен сообщениями работает в режиме disableWorker (который на самом деле не тестировался и создан только для поддержки устаревших браузеров и простоты отладки). Это поможет сузить проблему, чтобы получить минимальный тестовый пример, в котором проблема видна (предпочтительно доступный онлайн).

Хорошо, это интересно ... тестирование на localhost: 8443 на фиктивном сертификате (где имя хоста! = Localhost), он не кешируется. Когда я тестирую на реальном сервере, порт 443 с действующим коммерческим сертификатом, он кеширует (!) ... не совсем уверен, что с этим делать ... проведу еще несколько тестов, когда у меня будет немного времени, но для теперь я включу веб-воркеров и посмотрю, что произойдет. (но я думаю, что где-то есть проблема ...)

Я не совсем уверен, что верю мне .. поэтому я добавил несколько скриншотов ...

live

dev

Отключить кеш обязательно _не_ галочки ...
(конфигурация веб-сервера идентична)

Здесь что-нибудь еще можно сделать? Насколько я понимаю, это не похоже на ошибку в PDF.js, а скорее на пользовательскую реализацию.

Было бы неплохо иметь тестовый пример, чтобы мы могли воспроизвести этот (периодический?) Сбой.

Это ошибка, я сделаю онлайн-демонстрацию, но это займет немного времени и кода ...

Привет, у меня такая же проблема.

Здесь ничего кастомного не написано, только что скачал репо с Github
screencapture 7

@ subhadip-codeclouds Я не думаю, что у вас такая же проблема. Пожалуйста, откройте отдельный вопрос и предоставьте запрашиваемые данные.

@ subhadip-codeclouds Где я могу найти этот PDF-файл? У меня похожая проблема, и я хочу использовать ее в качестве тестового примера.

Я считаю, что у меня такая же проблема с рендерингом шрифтов в Ubuntu с Chrome (не тестировал другие платформы). Я использую последнюю версию pdf.js от master, и иногда PDF-файл будет выглядеть как PDF -файл @oddjobz, а иногда - как

Я действительно не знаю, что не так и как надежно воспроизвести. Однако это сценарий. Я использую React для создания динамического одностраничного веб-сайта. Пользователи часто нажимают на вкладку, которая создает iframe и отображает pdf.js внутри iframe. Учитывая то, как работает React и мой веб-сайт, iframe создается и уничтожается снова и снова. Это может занять некоторое время, но со временем я всегда буду получать искажения при визуализации шрифтов. И как только это произойдет с одним PDF-файлом, это начнется случайным образом с другими PDF-файлами. Некоторые всегда в порядке, а некоторые нет.

Есть ли что-нибудь (например, флаги отладки), которые я могу включить или сделать, чтобы понять, что происходит? Я не вижу ошибок или предупреждений в консоли.

Вот PDF-файл, который почти всегда заканчивается повреждением рендеринга шрифта при запуске.
https://datalanche-sec-public.s3.amazonaws.com/filings/0001047469-15-008315/a2226328zex-31_2.htm.pdf

Еще кое-что. Если я открою новую вкладку в Chrome с тем же URL-адресом, PDF-файлы будут исправлены. Однако, если я остаюсь на той же вкладке, перехожу на совершенно другой веб-сайт, а затем перехожу на свой веб-сайт (не используя кнопку «Назад»), PDF-файлы с поврежденными шрифтами по-прежнему повреждены. Кажется, что все, что происходит, повреждает память и / или кеш вкладки.

Возможно, это проблема кеширования в Chrome (подробнее см. Https://github.com/mozilla/pdf.js/issues/7751#issuecomment-256683285).

Есть новости по этому поводу? с той же проблемой

Хотя я все еще вижу это (необъяснимо) время от времени, это очень редко и действительно достаточно редко, я действительно перестал об этом беспокоиться. Проблема, с которой я столкнулся, заключалась в наложении операций. «Кажется» возможным работать с PDF-документом (например, следующей страницей), пока другая операция все еще выполняется, и это, кажется, вызывает проблему. Мое решение заключалось в том, чтобы обернуть все операции в класс, а затем вставить главную блокировку в точки входа и выхода, чтобы никакие операции, связанные с pdf, не могли конфликтовать - это «кажется» исправило для меня вещи. Я смутно предполагаю, что PDF-файлы работают в отдельном потоке или рабочем процессе, отсюда и возможность конфликта. Это было некоторое время назад, но по памяти я думаю, что многопоточность - это вариант, и я обнаружил решение, отключив его, что отрицательно сказалось на производительности, но решило проблему.

Со мной такое случается постоянно, но достаточно случайно, чтобы я не мог создать тестовый пример. Однако вполне возможно, что и в моем случае это повреждение памяти из-за потоковой передачи, но я думал, что Javascript был однопоточным?

Я думал, что Javascript однопоточный

Это. Я думаю, что означает @oddjobz (?), Что в Chrome может быть ошибка, когда вы рисуете более чем на одном холсте HTML5 за раз, вероятность возникновения дефекта высока. Но без воспроизводимого тестового примера сложно рассуждать и создавать содержательный отчет об ошибках Chromium.

Я думаю (по памяти) он использует возможность использовать новую функцию браузера, называемую «веб-воркеры», которая эффективно позволяет создавать потоки javascript .. если вы отключите эту функцию, а затем попытаетесь просмотреть «большой» PDF-файл, вы посмотреть "почему" эта функция используется ... :)

в нем есть возможность использовать новую функцию браузера под названием «веб-работники» ...
если вы отключите эту функцию, а затем попытаетесь просмотреть «большой» PDF-файл, вы увидите, «почему» эта функция используется

Обратите внимание, что OP дает команду отключить эту функцию, что означает, что Web Workers не используются, что перекладывает ответственность на браузер и не имеет ничего общего с «потоками» JavaScript.

Это немного тонко, Javascript является однопоточным, но Chrome - многопоточным, а веб-воркеры позволяют запускать два процесса Chrome и облегчают взаимодействие между ними. Я думаю, что только мастер получает доступ к DOM, но вы можете использовать подпотоки для интенсивного использования процессора, не блокируя поток пользовательского интерфейса. Еще веселее, когда вы обнаруживаете, что можете создавать веб-воркеров, которые не привязаны к определенному потоку или вкладке, чтобы они эффективно пережили перезагрузку страницы (т.е. были постоянными). Я вижу множество проблем, связанных с этим ...

Конечно, но мой комментарий заключается в том, что без потоковой передачи (то есть путем реализации моей собственной блокировки уровня потока) 99% этой проблемы исчезают. (для меня).

@oddjobz , @rpedela попробуйте отключить аппаратное ускорение / ускорение графического процессора и посмотрите , сохраняется ли проблема.

@yurydelendik , да, это было очевидно, одна из первых вещей, которые я попробовал. (нет разницы)

@yurydelendik , мое приложение работает более 6 месяцев, я рад, что все оставшиеся проблемы "разные" и, скорее всего, связаны с ошибкой пользователя или случайным странным документом. Проблема, с которой я столкнулся, которая, хотя и непостоянная, но воспроизводимая на 100%, исчезла. Это было (IMHO) вызвано перекрытием между операциями с документами, то есть процессом, начавшимся до того, как завершился предыдущий - многопоточность или нет, установка ручной блокировки, чтобы предотвратить запуск операций до того, как предыдущая завершила его. Легко воспроизводимый пример - это быстрое сканирование вперед по документу и обработка «следующего» начала до того, как предыдущая страница полностью завершила рендеринг.

Javascript является однопоточным, но Chrome - многопоточным, а веб-воркеры позволяют запускать два процесса Chrome и облегчают взаимодействие между ними. Я думаю, что только мастер получает доступ к DOM, но вы можете использовать подпотоки для интенсивного использования процессора, не блокируя поток пользовательского интерфейса.

Это утверждение с термином «веб-работник» сбивает с толку. Можете ли вы предоставить ссылки для проверки утверждений выше? Веб-воркеры не имеют доступа к DOM по дизайну, а PDF.js выполняет рисование в основном потоке. Вы имеете в виду процесс рендеринга Chrome? Тем не менее, единственный способ обновить DOM - из основного потока, а не из веб-воркеров.

Процесс запускается до того, как завершился предыдущий - поток или нет, установка ручной блокировки, чтобы предотвратить запуск операций до того, как предыдущая завершила, исправила его.

Что именно вы подразумеваете под «операциями» в этом контексте, это время жизни вызова API render() ?

@oddjobz Я только что прочитал эту

@oddjobz , @rpedela , @badams , @pholisma , @ subhadip-codeclouds, можете ли вы предоставить отдельный отчет об ошибке с точной конфигурацией (-ями), в которой вы столкнулись с проблемой, и точными шагами, когда можно воспроизвести проблему (включая PDF-файл)? если это индивидуальное решение, предоставьте публичную ссылку на него.

Хорошо, это код, о котором идет речь - вы можете видеть исправление на месте.

Специально для блокировки у меня есть такая процедура;


this.locked = true;
PDFJS.getDocument(path+doc_id).then(function(pdf) {
    $('#pdf-canvas-pages').text(pdf.numPages);
    self.pages = pdf.numPages;
    self.page = 1;
    self.pdf = pdf;
    pdf.getPage(1).then(function(page) { self.turnpage(); });
})

turnpage: function() {
    var self = this;
    self.pdf.getPage(self.page).then(function(page) {
        var canvas = document.getElementById('pdf-canvas');
        var ctx = canvas.getContext('2d');
        var unscaledViewport = page.getViewport(1);
        canvas.width = $('#pdf-canvas').width();
        var scale = canvas.width / unscaledViewport.width;
        var viewport = page.getViewport(scale);
        canvas.height = viewport.height;
        var renderContext = { canvasContext: ctx, viewport: viewport };
        page.render(renderContext);
        $('#pdf-canvas-page').text(self.page);
        self.locked = false;
    });
},

Да, именно поэтому я не настаивал на этом в то время, похоже, есть большое нежелание даже признать наличие проблемы - не говоря уже о том, что ее необходимо исправить.

Проблема с приведенным выше фрагментом была решена https://github.com/mozilla/pdf.js/pull/6571.

Ну, что я могу сказать, я использовал последнюю версию в середине 2016 года, и проблема все еще была. Я, кажется, помню, как мне тогда говорили (неоднократно), что это было исправлено. (и, как и многие другие, я видел, что этого явно не было)

В любом случае, для тех, кто видит ту же проблему, попробуйте вставить блокировку, как указано выше, и посмотрите, имеет ли это какое-либо значение ... это всего лишь две строки ...

@yurydelendik Это происходит довольно постоянно для наших пользователей (в основном, использующих Windows 7), но я смог воспроизвести это на OSX с последней версией, но не на 100% последовательно.

Мы не используем никакого специального кода, просто делаем следующее

<iframe
    style="height: 650px; width: 600px"
    src="/path/to/pdfjs/web/viewer.html?file=/path/to/file.pdf"
/>

Кажется, это зависит от ряда факторов, таких как наличие в документе какого-либо другого полужирного текста и начального уровня масштабирования (увеличение и уменьшение иногда исправляет это). Я также заметил, что это влияет только на предварительный просмотр, и печать, при загрузке pdf он выглядит идеально (я думаю, это потому, что pdf.js просто передает предоставленный файл пользователю).

Мы решили отказаться от использования этого решения и напрямую загрузить файл на компьютер пользователя, но я постараюсь найти время, чтобы придумать воспроизводимый тестовый пример, хотя вчера я уже потратил весь свой день на поиски этой ошибки ..

@badams , я могу подтвердить, что масштабирование также было для меня исправлением, как и следующая / предыдущая страница. У меня также сложилось впечатление, что выделение жирным шрифтом делает проблему более вероятной.

Я постараюсь найти время, чтобы придумать воспроизводимый тестовый пример.

@badams, спасибо, все, что принимает все варианты, когда участники пытаются воспроизвести проблему на своих компьютерах, будет работать, а полные примеры, опубликованные в Интернете, работают лучше всего (вы можете опубликовать полный пример в ветке gh-pages репозитория github).

Привет, ребята,

Я неправильно понял всю эту историю.
Исправление уже есть? Или какая-то реализация, которую я должен сделать?

С Уважением,
Тарчизио Перейра

Я неправильно понял всю эту историю.

Я не думаю, что кто-то знает.

Эта ветка закрыта, поскольку в ней нет точных инструкций по воспроизведению проблемы (и из-за некоторых вводящих в заблуждение рекомендаций в комментариях). Мы не ожидаем, что проблема будет воспроизводиться на 100%, но сделать так, чтобы она появлялась хотя бы раз из 10, было бы здорово.

Возможные элементы, из-за которых PDF.js может работать таким образом или содержать ошибку в коде:

  • HTTP-сервер или браузер неправильно обрабатывают запросы диапазона HTTP
  • Браузер неправильно обрабатывает загрузку шрифта или операцию холста
  • Пользовательское решение конфликтует с указанными выше операциями

FWIW Я видел это повреждение в редких случаях при развертывании pdf.js (v1.7.376). Наша обработка запроса диапазона кажется правильной. Сообщу, если найду надежные репро шаги ...

У нас была эта проблема только в Chrome, после изменения масштаба она исчезает. Поэтому мы установили showPreviousViewOnLoad в false и больше никогда не сталкивались с этой проблемой.

@TZanke, не могли бы вы пояснить, почему удаление showPreviousViewOnLoad меняет масштаб? Благодаря!

@tonyjin pdf.js autozoom вычисляет значение масштабирования и сохраняет его в локальном хранилище. После перезагрузки страницы автоматическое масштабирование не используется, вместо этого используется предыдущее рассчитанное значение масштабирования. И похоже, что снова возникла проблема с загрузкой этого значения.

Таким образом, при отключении showPreviousViewOnLoad функция автоматического масштабирования срабатывает каждый раз, масштабирует страницу правильно, и проблем с рендерингом не возникает.

@TZanke - Я попробовал ваш подход, но, к сожалению, иногда проблема все равно всплывает .. :(

Была ли эта страница полезной?
0 / 5 - 0 рейтинги

Смежные вопросы

snorp picture snorp  ·  95Комментарии

Vanuan picture Vanuan  ·  34Комментарии

syssgx picture syssgx  ·  29Комментарии

soa-x picture soa-x  ·  174Комментарии

Richard-Mlynarik picture Richard-Mlynarik  ·  32Комментарии