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)

Спасибо!

0 ответов

Для хрома еще нужен --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на самом деле не лежит в основе проекта.
Если вам нужна поддержка init или что-то еще, кромеtext(), вам нужно будет его добавить.
Явныйfile://запросы не будут выполняться, это сделано специально, но если вы действительно знаете, что делаете, вы будете знать, как заставить это работать на вас, а если вы этого не сделаете, вам не следует этого делать.


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

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

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

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