Получение файла JSON с использованием jQuery без веб-сервера

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

И один из требований был Should not require a web server, and should be able to run offline.,

я использовал jQuery и использовал $.getJSON() чтобы получить данные из .JSON файл. Я бросил это на моем WAMP локальный сервер, и он работал безупречно во всех трех основных браузерах (IE, Firefox, Chrome). Затем я переместил этот проект в Desktop По сути, без ЛОКАЛЬНОГО СЕРВЕРА.

На Firefox 30.0 он работал отлично. Нет проблем.

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

В Internet Explorer 11, однако... это не сработало. Зачем?

Вот что я использую. Это не сложно.

function loadTasks() {
  console.log("Loading tasks...");
  $.getJSON("data.json", function(result) {
    $.each(result, function(i, task) {
      $("#load_tasks").append(
        "<div class='row'><span class='data-task'>" + task.name +
        "</span> <span class='data-date'>" + task.date +
        "</span> <span class='data-name'>" + task.assigned +
        "</span> </div>");
    });
  });
}

а вот data.json

10 ответов

Это похоже на ошибку в jQuery. Эта ошибка была сообщена в jQuery. Статус ошибок исправлен. Но, похоже, ошибка все еще на свободе.

объяснение

Обычно в IE ajax реализуется через ActiveXObjects. Но в IE11 они внесли некоторые изменения в реализацию ActiveXObject, если мы попытаемся сделать следующее:

typeof(window.ActiveXObject)

вместо того, чтобы возвращать "функцию", как сказано в IE документах, он возвращает undefined, jQuery использовал это для переключения между xhr в обычных браузерах и между одним в IE. Поскольку проверка оценивается как неопределенная, запускается код, используемый для создания объекта xhr в обычных браузерах (что, как ни странно, является ошибкой для нелокальных файлов, работает нормально).

В сообщении об ошибке, поданном на bugs.jquery.com, репортер об ошибках спрашивает:

Чтобы решить проблему, достаточно изменить условие: используйте "window.ActiveXObject!== undefined?" вместо "window.ActiveXObject?"

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

var activex; // save activex somewhere so that it only need to check once
if ( activex === undefined ) 
  try { 
    new ActiveXObject("MSXML2.XMLHTTP.3.0");
    activex = true; 
  } catch (e) { 
    activex = false 
  }
xhr = activex ? createActiveXHR() : createStandardXHR(); 

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

function showData(){
function getLocalPath(fileName/*file name assuming in same directory*/){
    // Remove any location or query part of the URL
    var directoryPath = window.location.href.split("#")[0].split("?")[0];
    var localPath;
    if (directoryPath.charAt(9) == ":") {
        localPath = unescape(directoryPath.substr(8)).replace(new RegExp("/","g"),"\\");
    }
    localPath = localPath.substring(0, localPath.lastIndexOf("\\")+1)+fileName;
    console.log(localPath);
    return localPath;
}

var content = null;
    try {
        var fileSystemObj = new ActiveXObject("Scripting.FileSystemObject");
        var file = fileSystemObj.OpenTextFile(getLocalPath("data.json"),1);
        content = file.ReadAll();
        file.Close();
    } catch(ex) {
        console.log(ex);
    }
    console.log(content);
}
showData();

Запустите ваш HTML-файл в браузере из пути к файлу и попробуйте запустить вышеупомянутую функцию в консоли. Он выведет содержимое файла json в консоль.

Вы можете создать оболочку для приведенного выше кода для использования в запросе XHR. Дайте мне знать, если вам нужна помощь в интеграции этого с запросом jQuery AJAX.

jQuery .getJSON использует ajax. http://api.jquery.com/jquery.getjson/

.ajax использует XMLHttpRequest

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

Через безопасность в глубине: локальные веб-страницы

http://blog.chromium.org/2008/12/security-in-depth-local-web-pages.html

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

Вы открываете локальную веб-страницу в своем браузере.

На локальной веб-странице создается фрейм-фрейм, источник которого https://mail.google.com/mail/.

Поскольку вы вошли в Gmail, фрейм загружает сообщения в ваш почтовый ящик.

Локальная веб-страница считывает содержимое фрейма, используя JavaScript для доступа к фреймам [0].document.documentElement.innerHTML. (Веб-страница в Интернете не сможет выполнить этот шаг, потому что она будет происходить из источника не из Gmail; политика того же источника вызовет сбой чтения.)

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

Решение для данных, которое не нуждается в политике безопасности того же источника, является дополненным json. Поскольку jsonp не является безопасным форматом для данных. У Jsonp нет политики того же происхождения.

/* secured json */
{
  "one": "Singular sensation",
  "two": "Beady little eyes",
  "three": "Little birds pitch by my doorstep"
}

/* padded json aka jsonp */
Mycallback ({
  "one": "Singular sensation",
  "two": "Beady little eyes",
  "three": "Little birds pitch by my doorstep"
});

Так как с jsonp json обернут в допустимую функцию javascript, его можно открыть так же, как любой добавил бы любой javascript на страницу.

var element = document.createElement("script");
element.src = "jsonp.js";
document.body.appendChild(element);

И ваш обратный вызов обрабатывает данные,

function Mycallback(jsondata) {
}

Функционально это то же самое, что и запрос ajax, но отличается, потому что это запрос jsonp, который на самом деле проще.

Библиотеки jQuery также напрямую поддерживают jsonp http://api.jquery.com/jquery.getjson/ Посмотрите пример с использованием JSONP API от Flickr; если кто-то не знал о двойных стандартах, они могут даже не заметить, что используется jsonp.

(function() { /* jsonp request note callback in url, otherwise same json*/
  var flickerAPI = "http://api.flickr.com/services/feeds/photos_public.gne?jsoncallback=?"; 
  $.getJSON( flickerAPI, {
    tags: "mount rainier",
    tagmode: "any",
    format: "json"
  })
    .done(function( data ) {
      $.each( data.items, function( i, item ) {
        $( "<img>" ).attr( "src", item.media.m ).appendTo( "#images" );
        if ( i === 3 ) {
          return false;
        }
      });
    });
})();

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

Используйте --allow-file-access-from-files, чтобы включить его в Chrome. https://code.google.com/p/chromium/issues/detail?id=40787

К вашему сведению: они работают над зашифрованным json http://tools.ietf.org/html/draft-ietf-jose-json-web-encryption-08 Я совершенно уверен, что не будет никакого способа использовать это локально, намерение чтобы сделать это действительно, действительно безопасно.

То, что вы нам не хватает, было использование appCache,

<html manifest="example.appcache">

в вашем добавлении HTACCESS

AddType text/cache-manifest .appcache

внутри example.appcache

CACHE MANIFEST
data.json
index.php
someimage.png
# continue for all the file needed for the web site to work

Это означает, что после подключения и загрузки контента, когда он больше не нужен. на другой ноте вы не должны иметь возможность получить доступ к file:// URI, хотя XHR/ajax, так как нет способа отправить контент, если вы хотите, чтобы он находился в автономном режиме, вы могли бы просто встроить содержимое файла json в ваш код в виде строки и просто использовать var jsonStr = '{}'; var jsonObj = JSON.parse(jsonStr); где jsonStr - ваш код это означало бы отсутствие подключений к серверу, поскольку не было бы запроса ajax/XHR

Источник: /questions/28795432/getjson-ne-rabotaet-v-ie-11-na-vneshnih-kompyuterah/28795446#28795446

Размещать ответ на тот случай, если кто-то столкнется с ним. В моем случае IE загружал версию jquery, которая, очевидно, вызывает ошибку "JSON undefined". Вот что я сделал, чтобы решить это:

<!--[if lt IE 9]>
    <script src="http://code.jquery.com/jquery-1.10.2.js"></script>
<![endif]-->
<!--[if gte IE 9]><!-->
    <script src="http://code.jquery.com/jquery-2.0.3.js"></script>
<!--<![endif]-->

Последний из них - jquery 2.1.1: прямая ссылка, но там написано:

(IE <9 не поддерживается)

Так что я думаю, JQuery 1.11.1: прямая ссылка

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

Вот рабочее решение. Я включил руль, потому что он чище.

<!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>JSON TEST</title>

    </head>
    <body>

        <div id="load-tasks">

        </div>


        <script src="jquery.min.js"></script>
        <script src="handlebars.min.js"></script>


        <script id="tasks-template" type="text/x-handlebars-template">
            {{#each .}}
            <div class="row">
                <span class="data-task">
                    {{this.name}}
                </span> <span class="data-date">
                    {{this.date}}
                </span> <span class="data-name">
                    {{this.assigned}}
                </span>
            </div>
            {{/each}}
        </script>

        <script>
            $(function () {
                var loadTasksContainer = $('#load-tasks'),
                    tasksTemplate = Handlebars.compile($('#tasks-template').html());

                $.ajax({
                    type: "GET",
                    url: "data.json",
                    dataType: "json",
                    cache: false,                    
                    success: function (data) {
                        var html = tasksTemplate(data);
                        loadTasksContainer.append(html);
                    },
                    error: function (xhr, status, error) {
                        //log error and status
                    }
                });

            });
        </script>
    </body>
    </html>

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

Пример файла data.jsonp:

loadTasks([
    {name:"Task 1", date:"Date 1", assigned:"John Doe"},
    {name:"Task 2", date:"Date 2", assigned:"Jane Doe"}
]);

Затем на своей странице просто загрузите data.jsonp, используя тег script:

<script>
function loadTasks(tasks) {
    $.each(tasks, function (i, task) {
        $("#load_tasks").append(
            "<div class='row'><span class='data-task'>" + task.name +
            "</span> <span class='data-date'>" + task.date +
            "</span> <span class='data-name'>" + task.assigned +
            "</span> </div>");
    });  
}
</script>
<script src="data.jsonp"></script>

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

Если ваша проблема заключается в том, что его трудно установить, попробуйте это: https://www.npmjs.org/package/http-server

В вашей оболочке вы идете в каталог, где находятся ваши файлы, а затем вы просто набираете

http-server ./ -p 12345 

где 12345 может быть изменен любым действительным и еще не использованным портом по вашему выбору.

Попробуйте включить error Перезвоните; jqxhr.responseText может по-прежнему содержать data.json,

data.json

{"data":{"abc":[123]}}

json.html

<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="jquery-1.11.1.min.js"></script>
<script type="text/javascript">
$(function() {
  $.getJSON(document.location.protocol + "data.json")
  .then(function(data, textStatus, jqxhr) {
    var response = JSON.parse(data);
    console.log(textStatus, response);
  } 
   // `error` callback
  , function(jqxhr, textStatus, errorThrown) {
      var response = JSON.parse(jqxhr.responseText);
      console.log(textStatus, errorThrown, response);
      $("body").append(response.data.abc);
  });
})
</script>
</head>
<body>
</body>
</html>
<meta http-equiv="X-UA-Compatible" content="IE=edge"> 

Попробуйте добавить этот метатег и проверьте в IE

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