Получение файла 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