Не вдається відкрити локальний файл - Chrome: Не дозволяється завантажувати локальний ресурс


102

Тестовий браузер: версія 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>для отримання доступу до місцевих джерел
dandavis

Відповіді:


64

Знайте, це щось старе, але перегляньте багато запитань, подібних до цього ...

Ми багато використовуємо 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
користувач1723453

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 я додав файл-обробник, який називається 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:. Тож найкраще, що ви можете зробити, - це використовувати такий код, як мій, для доступу до файлів десь на мережевому диску.


Звучить добре, але як ви обробляєте авторизацію (дозволи на читання)? Що робити, якщо не всім користувачам дозволено переглядати даний файл? Чи не потрібно буде виконувати зчитування на ім'я користувача, що запитує?
Тімі

Чому ви використовуєте веб-клієнт, щоб відкрити локальний файл? А для мене він намагається відкрити C: \ SomeNetworkPath \ ...
Кев

Якщо ми не використовуємо кутовий, це все-таки можливо?
Ахмад.

Це була корисна відповідь, але це дуже вплинуло б на час завантаження веб-сторінки, якщо у вас є сотні зображень, які відображаються та завантажуються таким чином за допомогою цього дескриптора ashx.
Джамшаїд Камран

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

6
На GoogleChrome 66 він не працює. Chrome починається з цього прапора, але все одно показує, що локальний файл неможливо відкрити.
Radon8472

16

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

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 з розширених налаштувань, якщо ви зіткнетеся з помилкою доступу з перехресним джерелом.


6

Ви не зможете завантажити зображення поза каталогом проекту або з каталогу рівня користувача, отже, "не вдається отримати доступ до попередження про локальний ресурс".

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

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

5

Ця проблема виникає, коли я використовую PHP як мову на стороні сервера, і навколо цього було згенерувати базове кодування мого зображення перед надсиланням результату клієнту

$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 потребує URL-адреси 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 тощо), але це збиває людей з місця бачити їх локальний вміст у вікні браузера, навіть якщо сценарій не може сказати, що він показує ...
dandavis

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

1

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

Знайдіть нижче код, щоб перетворити кожен мережевий шлях (або локальний шлях) src в байт. Він точно покаже всі зображення з мережевим шляхом (або локальним шляхом) у 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.