Chrome - Fetch API не может загрузить файл. Как обойтись?

У меня есть два файла:

index.html

<html>
<head>
<meta charset = "utf-8" />
<title>Web Page</title>
<style type = "text/css">
.text {
    display: inline-block;
    font-family: tahoma;
    font-size: 14px;
    max-width: 400px;
    background-color: #ddedff;
    padding: 10px;
    text-align: justify;
}
</style>
<script type = "text/javascript" src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type = "text/javascript">
$(function(){
    get_data('info.txt');
});
function get_data(file) {
    var request = new Request(file);
    fetch(request).then(function(response) {
        return response.text().then(function(text) {
            $('.text').html(text);
        });
    });
}
</script>
</head>
<body>
    <div class = "text"></div>
</body>
<html>

info.txt

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Когда я открываю на Mozilla Firefox файл: README.html через этот локальный URI:

file:///C:/testing/README.html

он работает как положено, я имею в виду, текст в файле: info.txt отображается правильно.

Но когда я открываю тот же URI на Google Chrome, я получаю пустой экран и следующую ошибку на консоли:

README.html:26 Fetch API cannot load file:///C:/testing/README.md. URL scheme must be "http" or "https" for CORS request.
get_data @ README.html:26
README.html:26 Uncaught (in promise) TypeError: Failed to fetch
    at get_data (README.html:26)
    at HTMLDocument.<anonymous> (README.html:21)
    at l (jquery.min.js:2)
    at c (jquery.min.js:2)

Есть ли у вас, что я могу сделать, чтобы я мог открывать локальные файлы на Google Chrome так же, как на Mozilla Firefox?

Если мне нужно немного подправить:

chrome://flags/

это приемлемо для меня.

РЕДАКТИРОВАТЬ

Я попытался запустить Google Chrome из командной строки с флагом: --allow-file-access-from-files, как рекомендовано здесь, но теперь получаю следующую ошибку:

README.html:26 Fetch API cannot load file:///C:/testing/README.md. URL scheme "file" is not supported.
get_data @ README.html:26
README.html:26 Uncaught (in promise) TypeError: Failed to fetch
    at get_data (README.html:26)
    at HTMLDocument.<anonymous> (README.html:21)
    at l (jquery.min.js:2)
    at c (jquery.min.js:2)

Спасибо!

Ответ на вашу проблему - в сообщении об ошибке, которое предоставил Chrome. Chrome не позволяет загружать локальные файлы через file:///... из соображений безопасности. Если это приложение, над которым вы работаете только для локального использования, вы можете загрузить приложение Chrome, которое создает для вас веб-сервер в определенном локальном каталоге. Веб-сервер для Chrome - это тот, который Google предлагает при работе над своими лабораториями кода.

Denno 23.04.2018 01:15

твика chrome://flags/ нет, только твик командной строки. Запустите Chrome с параметром командной строки, который позволяет страницам file:/// получать доступ к таким ресурсам file:/// - я не знаю эту возможность, быстрый поиск в Google должен помочь

Jaromanda X 23.04.2018 01:20

Похоже, что Chrome fetch в наши дни просто не работает со схемой URL file://. Вы рассматривали XHR? Или, что еще лучше, использовать локальный http-сервер?

Jaromanda X 23.04.2018 02:04

@Jaromanda, спасибо, это помогло

davidesp 23.04.2018 03:36
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
11
4
27 238
1

Ответы 1

Для Chrome вам по-прежнему нужен --allow-file-access-from-files (и я рекомендую установить отдельный хром и использовать его исключительно для этих проектов, чтобы оставаться в безопасности), но просто установите прокладку fetch() для XMLHttpRequest для запросов file://:

if (/^file:////.test(location.href)) {
    let path = './';
    let orig = fetch;
    window.fetch = (resource) => ((/^[^/:]*:/.test(resource)) ?
        orig(resource) :
        new Promise(function(resolve, reject) {
            let request = new XMLHttpRequest();

            let fail = (error) => {reject(error)};
            ['error', 'abort'].forEach((event) => { request.addEventListener(event, fail); });

            let pull = (expected) => (new Promise((resolve, reject) => {
                if (
                    request.responseType == expected ||
                    (expected == 'text' && !request.responseType)
                )
                    resolve(request.response);
                else
                    reject(request.responseType);
            }));

            request.addEventListener('load', () => (resolve({
                arrayBuffer : () => (pull('arraybuffer')),
                blob        : () => (pull('blob')),
                text        : () => (pull('text')),
                json        : () => (pull('json'))
            })));
            request.open('GET', resource.replace(/^//, path));
            request.send();
        })
    );
}

Эта прокладка будет;

  • активировать только для html-файлов, открытых локально (внешний оператор if),
  • вызовите обычный fetch() для любого URL-адреса, который не указывает протокол (и, следовательно, запросы, отличные от file://), и
  • заменит абсолютные пути (/root/bob.html) на пути, относящиеся к текущему пути (так как это будет опасно оценивать C:\ или эквивалент)

Установите path на другое значение, если ваш index.html на самом деле не находится в корне проекта. Если вам нужна поддержка в этом или чего-либо другого, кроме text(), вам нужно будет ее добавить. Явные запросы file:// не будут выполняться, это сделано специально, но если вы В самом деле действительно знаете, что делаете, вы будете знать, как заставить это работать для вас, а если вы этого не сделаете, вам не следует этого делать.


Следующее полезно, если вы собираетесь делать это для нескольких файлов. Замените './' на document.currentScript.getAttribute('data-root'). Теперь вы можете поместить этот фрагмент в отдельный файл, скажем, filesystemHelper.js, и вызвать его в различных файлах:

<script src = "../filesystemHelper.js" data-root = "../"></script>

Довольно шикарно.

как вы используете этот код?

Frank Z. 31.03.2021 23:48

Другие вопросы по теме