Не удается открыть локальный файл - Chrome: не разрешено загружать локальный ресурс


107

Тестовый браузер: Версия Chrome: 52.0.2743.116

Это простой javascript, который предназначен для открытия файла изображения с локального компьютера, например C: \ 002.jpg.

function run(){

   var URL = "file:///C:\002.jpg";

   window.open(URL, null);

}
run();

Вот мой пример кода. https://fiddle.jshell.net/q326vLya/3/

Пожалуйста, дайте мне любые подходящие предложения.


используйте <input type=file>для доступа к местным
ресурсам

Ответы:


66

Знайте, что это старовато, но посмотрите много таких вопросов ...

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

Мы использовали «Веб-сервер для Chrome». Вы запускаете его, выбираете папку, с которой хотите работать, и переходите по URL-адресу (например, 127.0.0.1: выбранный вами порт)

Это простой сервер и не может использовать PHP, но для простой работы может быть вашим решением:

https://chrome.google.com/webstore/detail/web-server-for-chrome/ofhbbkphhbklhfoeikjpcbhemlocgigb


1
Вуди: Большое спасибо! Этот подход мне помог. Я запускаю локальный Tomcat + локальную корзину AWS S3 в Windows 10. Теперь я могу переключаться между работающим сервером AWS и локальным. Ура. Q
user1723453 04

20

Хорошо, ребята, я полностью понимаю причины безопасности этого сообщения об ошибке, но иногда нам нужен обходной путь ... и вот мой. Он использует ASP.Net (а не JavaScript, на котором основан этот вопрос), но, надеюсь, будет кому-то полезен.

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

введите описание изображения здесь

Эта веб-страница использует AngularJS 1.x для перечисления различных ярлыков.

Первоначально моя веб-страница пыталась напрямую создать <a href..>элемент, указывающий на файлы, но это приводило к Not allowed to load local resourceошибке " ", когда пользователь нажимал на одну из этих ссылок.

<div ng-repeat='sc in listOfShortcuts' id="{{sc.ShtCut_ID}}" class="cssOneShortcutRecord" >
    <div class="cssShortcutIcon">
        <img ng-src="{{ GetIconName(sc.ShtCut_PathFilename); }}">
    </div>
    <div class="cssShortcutName">
        <a ng-href="{{ sc.ShtCut_PathFilename }}" ng-attr-title="{{sc.ShtCut_Tooltip}}" target="_blank" >{{ sc.ShtCut_Name }}</a>
    </div>
</div>

Решением было заменить эти <a href..>элементы этим кодом, чтобы вызвать функцию в моем контроллере Angular ...

<div ng-click="OpenAnExternalFile(sc.ShtCut_PathFilename);" >
    {{ sc.ShtCut_Name }}
</div>

Сама функция очень простая ...

$scope.OpenAnExternalFile = function (filename) {
    //
    //  Open an external file (i.e. a file which ISN'T in our IIS folder)
    //  To do this, we get an ASP.Net Handler to manually load the file, 
    //  then return it's contents in a Response.
    //
    var URL = '/Handlers/DownloadExternalFile.ashx?filename=' + encodeURIComponent(filename);
    window.open(URL);
}

И в моем проекте ASP.Net я добавил файл Handler, DownloadExternalFile.aspxкоторый содержал этот код:

namespace MikesProject.Handlers
{
    /// <summary>
    /// Summary description for DownloadExternalFile
    /// </summary>
    public class DownloadExternalFile : IHttpHandler
    {
        //  We can't directly open a network file using Javascript, eg
        //      window.open("\\SomeNetworkPath\ExcelFile\MikesExcelFile.xls");
        //
        //  Instead, we need to get Javascript to call this groovy helper class which loads such a file, then sends it to the stream.  
        //      window.open("/Handlers/DownloadExternalFile.ashx?filename=//SomeNetworkPath/ExcelFile/MikesExcelFile.xls");
        //
        public void ProcessRequest(HttpContext context)
        {
            string pathAndFilename = context.Request["filename"];               //  eg  "\\SomeNetworkPath\ExcelFile\MikesExcelFile.xls"
            string filename = System.IO.Path.GetFileName(pathAndFilename);      //  eg  "MikesExcelFile.xls"

            context.Response.ClearContent();

            WebClient webClient = new WebClient();
            using (Stream stream = webClient.OpenRead(pathAndFilename))
            {
                // Process image...
                byte[] data1 = new byte[stream.Length];
                stream.Read(data1, 0, data1.Length);

                context.Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}", filename));
                context.Response.BinaryWrite(data1);

                context.Response.Flush();
                context.Response.SuppressContent = true;
                context.ApplicationInstance.CompleteRequest();
            }
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }

Вот и все.

Теперь, когда пользователь нажимает на одну из моих ссылок OpenAnExternalFileбыстрого доступа , он вызывает функцию, которая открывает этот файл .ashx, передавая ему путь + имя файла, который мы хотим открыть.

Этот код обработчика загружает файл, а затем передает его содержимое обратно в HTTP-ответе.

И, готово, веб-страница открывает внешний файл.

Уф! Опять же - есть причина, по которой Chrome выдает это Not allowed to load local resourcesисключение, поэтому будьте осторожны с этим ... но я публикую этот код, чтобы продемонстрировать, что это довольно простой способ обойти это ограничение.

Только один последний комментарий: исходный вопрос хотел открыть файл " C:\002.jpg". Вы не можете этого сделать. Ваш веб-сайт будет находиться на одном сервере (со своим собственным диском C:) и не будет иметь прямого доступа к собственному диску C: вашего пользователя. Поэтому лучшее, что вы можете сделать, - это использовать код вроде моего для доступа к файлам где-нибудь на сетевом диске.


Звучит хорошо, но как вы обрабатываете авторизацию (разрешения на чтение)? Что, если не всем пользователям разрешено просматривать данный файл? Разве вам не нужно было бы выполнять чтение от имени запрашивающего пользователя?
Timi

Почему вы используете веб-клиент для открытия локального файла? И для меня он пытается открыть C: \ SomeNetworkPath \ ...
Кев,

Если мы не используем angular, возможно ли это?
Ахмад, Тр,

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

17

1) Откройте свой терминал и введите

npm install -g http-server

2) Перейдите в корневую папку, в которой вы хотите хранить файлы, и введите:

http-server ./

3) Прочтите вывод терминала, http://localhost:8080появится что-то вроде .

Все, что там есть, можно будет достать. Пример:

background: url('http://localhost:8080/waw.png');


http-сервер имеет проблему, которая теперь вызывает ошибки - вы можете понизить ее до 0.9, хотя для исправления - см. stackoverflow.com/questions/56364464/…
Брайан Бернс,

Для меня это был самый простой ответ. Сработало 100%. Благодарность!
robrecord

17

Chrome специально блокирует доступ к локальным файлам таким образом из соображений безопасности.

Вот обходной путь, чтобы включить флаг в Chrome (и открыть вашу систему до уязвимостей):

c: \ Program Files (x86) \ google \ chrome \ Application \ chrome.exe --allow-file-access-from-files


4
Я попытался выполнить решение "c: \ path \ chrome.exe" -allow-file-access-from-files, но не могу его открыть. Пожалуйста, проверьте этот сайт fiddle.jshell.net/q326vLya/3 . Что я делаю не так?
KBH

9
На GoogleChrome 66 он не работает. Chrome запускается с этим флагом, но он по-прежнему показывает, что локальный файл не может быть открыт.
Radon8472 06

9

Есть обходной путь с использованием веб-сервера для Chrome .
Вот шаги:

  1. Добавьте расширение в хром.
  2. Выберите папку (C: \ images) и запустите сервер на желаемом порту.

Теперь легко получить доступ к вашему локальному файлу:

function run(){
   // 8887 is the port number you have launched your serve
   var URL = "http://127.0.0.1:8887/002.jpg";

   window.open(URL, null);

}
run();

PS: Вам может потребоваться выбрать опцию CORS Header в расширенных настройках, если вы столкнетесь с какой-либо ошибкой доступа с перекрестным источником.


6

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

Но если бы вы поместили файл в корневую папку вашего проекта, как в, {rootFolder}\Content\my-image.jpgи ссылались на него так:

<img src="/Content/my-image.jpg" />

5

Эта проблема возникает, когда я использую PHP в качестве языка на стороне сервера, и работа заключалась в том, чтобы сгенерировать соединение base64 моего изображения перед отправкой результата клиенту.

$path = 'E:/pat/rwanda.png';
$type = pathinfo($path, PATHINFO_EXTENSION);
$data = file_get_contents($path);
$base64 = 'data:image/' . $type . ';base64,' . base64_encode($data);

Думаю, может дать кому-то идею создать свою собственную работу вокруг

Благодарность


2

Google Chrome не позволяет загружать локальные ресурсы из соображений безопасности. Chrome нужен http-адрес. Internet Explorer и Edge позволяют загружать локальные ресурсы, но Safari, Chrome и Firefox не позволяют загружать локальные ресурсы.

Перейдите в папку с файлом и запустите оттуда Python Server.

python -m SimpleHttpServer

затем поместите этот URL в функцию:

function run(){
var URL = "http://172.271.1.20:8000/" /* http://0.0.0.0:8000/ or http://127.0.0.1:8000/; */
window.open(URL, null);
}

2

Если у вас установлен php - вы можете использовать встроенный сервер. Просто откройте целевой каталог с файлами и запустите

php -S localhost:8001

1

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

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

Смотрите также:


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

1
@dandavis да, ты прав, но все же я верю, что можно предотвратить это. Помимо ошибок в некоторых реализациях (если вы не можете открыть локальный ресурс, вы, вероятно, в большей безопасности), могут быть некоторые конкретные сценарии, когда другие люди смотрят на ваш экран (приложения для совместного использования экрана или просто за вашей спиной в вашем офисе ), и вы не хотите, чтобы ваши изображения (потенциально кредитная карта или частное изображение) можно было открывать, просто посетив некоторые веб-сайты, которые могут угадать местоположение в вашей локальной файловой системе ...
Прак,

1

Вам просто нужно заменить все сетевые пути изображений на байтовые строки в сохраненной строке Encoded HTML. Для этого вам потребуется HtmlAgilityPack для преобразования строки Html в документ Html. https://www.nuget.org/packages/HtmlAgilityPack

Найдите ниже код для преобразования каждого сетевого пути src изображения (или локального пути) в байтовый sting. Он обязательно будет отображать все изображения с сетевым путем (или локальным путем) в IE, Chrome и Firefox.

string encodedHtmlString = Emailmodel.DtEmailFields.Rows[0]["Body"].ToString();

// Decode the encoded string.
StringWriter myWriter = new StringWriter();
HttpUtility.HtmlDecode(encodedHtmlString, myWriter);
string DecodedHtmlString = myWriter.ToString();

//find and replace each img src with byte string
HtmlDocument document = new HtmlDocument();
document.LoadHtml(DecodedHtmlString);
document.DocumentNode.Descendants("img")
    .Where(e =>
    {
        string src = e.GetAttributeValue("src", null) ?? "";
        return !string.IsNullOrEmpty(src);//&& src.StartsWith("data:image");
    })
    .ToList()
    .ForEach(x =>
        {
        string currentSrcValue = x.GetAttributeValue("src", null);                                
        string filePath = Path.GetDirectoryName(currentSrcValue) + "\\";
        string filename = Path.GetFileName(currentSrcValue);
        string contenttype = "image/" + Path.GetExtension(filename).Replace(".", "");
        FileStream fs = new FileStream(filePath + filename, FileMode.Open, FileAccess.Read);
        BinaryReader br = new BinaryReader(fs);
        Byte[] bytes = br.ReadBytes((Int32)fs.Length);
        br.Close();
        fs.Close();
        x.SetAttributeValue("src", "data:" + contenttype + ";base64," + Convert.ToBase64String(bytes));                                
    });

string result = document.DocumentNode.OuterHtml;
//Encode HTML string
string myEncodedString = HttpUtility.HtmlEncode(result);

Emailmodel.DtEmailFields.Rows[0]["Body"] = myEncodedString;

1

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

chrome.exe --allow-file-access-from-files

Прочтите это для более подробной информации

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

function getroutes(list){ 
    list.forEach(function(element) { 
        app.get("/"+ element, function(req, res) { 
            res.sendFile(__dirname + "/public/extracted/" + element); 
       }); 
   }); 
}

Я вызвал эту функцию, передав список имен файлов в каталоге, __dirname/public/extractedи она создала разные маршруты для каждого имени файла, который я смог отобразить на стороне сервера.


0

Это решение сработало для меня на PHP. Он открывает PDF-файл в браузере.

// $path is the path to the pdf file
public function showPDF($path) {
    if($path) {
        header("Content-type: application/pdf");
        header("Content-Disposition: inline; filename=filename.pdf");
        @readfile($path);
    }
}

0

Я столкнулся с этой проблемой, и вот мое решение для Angular. Я обернул папку с ресурсами Angular в функцию encodeURIComponent (). Это сработало. Но все же я хотел бы узнать больше о рисках этого решения, если они есть:

`` `const URL = ${encodeURIComponent(/assets/office/file_2.pdf )} window.open (URL)

I used Angular 9, so this is my url when I clicked open local file:
```http://localhost:4200/%2Fassets%2Foffice%2Ffile_2.pdf```
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.