Nie można otworzyć pliku lokalnego - Chrome: nie można załadować zasobu lokalnego

107

Przeglądarka testowa: wersja Chrome: 52.0.2743.116

Jest to prosty skrypt javascript, który służy do otwierania pliku obrazu z lokalnego, takiego jak „C: \ 002.jpg”

function run(){

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

   window.open(URL, null);

}
run();

Oto mój przykładowy kod. https://fiddle.jshell.net/q326vLya/3/

Proszę o wszelkie odpowiednie sugestie.

KBH
źródło
użyj, <input type=file>aby uzyskać dostęp do lokalnych zasobów
dandavis

Odpowiedzi:

66

Wiem, że to trochę stare, ale zobacz wiele takich pytań ...

Często używamy Chrome na zajęciach i jest to konieczne do pracy z lokalnymi plikami.

To, czego używaliśmy, to „serwer sieciowy dla Chrome”. Uruchamiasz go, wybierasz folder, z którym chcesz pracować i przechodzisz do adresu URL (np. 127.0.0.1:port, który wybrałeś)

Jest to prosty serwer i nie może używać PHP, ale do prostej pracy może być twoim rozwiązaniem:

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

Drzewiasty
źródło
1
Woody: wielkie dzięki! Takie podejście mi pomogło. Uruchamiam lokalny Tomcat + lokalny wiaderko AWS S3 na Windows 10. Teraz mogę przełączać się między aktywnym serwerem AWS a lokalnym. Twoje zdrowie. Q
user1723453
20

Dobra ludzie, całkowicie rozumiem powody bezpieczeństwa stojące za tym komunikatem o błędzie, ale czasami potrzebujemy obejścia ... i oto moje. Używa ASP.Net (zamiast JavaScript, na którym opierało się to pytanie), ale mam nadzieję, że przyda się komuś.

Nasza wewnętrzna aplikacja ma stronę internetową, na której użytkownicy mogą tworzyć listy skrótów do przydatnych plików rozsianych po całej naszej sieci. Kiedy klikną jeden z tych skrótów, chcemy otworzyć te pliki ... ale oczywiście błąd Chrome zapobiega temu.

wprowadź opis obrazu tutaj

Ta strona używa AngularJS 1.x do wyświetlania listy różnych skrótów.

Początkowo moja strona internetowa próbowała bezpośrednio utworzyć <a href..>element wskazujący na pliki, ale spowodowało to Not allowed to load local resourcebłąd „ ”, gdy użytkownik kliknął jeden z tych odsyłaczy.

<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>

Rozwiązaniem było zastąpienie tych <a href..>elementów tym kodem, aby wywołać funkcję w moim kontrolerze Angular ...

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

Sama funkcja jest bardzo prosta ...

$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);
}

W moim projekcie ASP.Net dodałem plik Handler o nazwie, DownloadExternalFile.aspxktóry zawierał ten kod:

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;
            }
        }
    }

I to wszystko.

Teraz, gdy użytkownik kliknie jedno z moich łączy Skrótów, wywołuje OpenAnExternalFilefunkcję, która otwiera ten plik .ashx, przekazując mu ścieżkę + nazwę pliku, który chcemy otworzyć.

Ten kod obsługi ładuje plik, a następnie przekazuje jego zawartość z powrotem w odpowiedzi HTTP.

Po wykonaniu zadania strona internetowa otwiera zewnętrzny plik.

Uff! Ponownie - istnieje powód, dla którego Chrome wyrzuca ten „Not allowed to load local resources ” wyjątek, więc postępuj ostrożnie z tym… ale publikuję ten kod tylko po to, aby zademonstrować, że jest to dość prosty sposób obejścia tego ograniczenia.

Jeszcze tylko jeden komentarz: pierwotne pytanie dotyczyło otwarcia pliku „C:\002.jpg ”. Nie możesz tego zrobić. Twoja witryna będzie znajdować się na jednym serwerze (z własnym dyskiem C:) i nie będzie mieć bezpośredniego dostępu do własnego dysku C: użytkownika. Więc najlepsze, co możesz zrobić, to użyć kodu takiego jak mój, aby uzyskać dostęp do plików gdzieś na dysku sieciowym.

Mike Gledhill
źródło
Brzmi dobrze, ale jak radzisz sobie z autoryzacją (uprawnieniami do odczytu)? A co, jeśli nie wszyscy użytkownicy mogą przeglądać dany plik? Czy nie musiałbyś dokonywać odczytu w imieniu żądającego użytkownika?
Timi,
Dlaczego używasz klienta internetowego do otwierania pliku lokalnego? A dla mnie próbuje otworzyć C: \ SomeNetworkPath \ ...
Kev
Jeśli nie używamy kątów, czy nadal jest to możliwe?
Ahmad.Tr
To była przydatna odpowiedź, ale bardzo wpłynęłaby na czas ładowania strony internetowej, jeśli masz setki obrazów renderowanych i pobieranych w ten sposób za pomocą tego uchwytu ashx.
Jamshaid Kamran
17

1) Otwórz terminal i wpisz

npm install -g http-server

2) Przejdź do folderu głównego, w którym chcesz udostępniać pliki i wpisz:

http-server ./

3) Przeczytaj wyjście terminala, coś http://localhost:8080się pojawi.

Wszystko tam będzie można dostać. Przykład:

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

Alex
źródło
Serwer http ma teraz problem powodujący błędy - możesz jednak obniżyć go do wersji 0.9, aby go naprawić - zobacz stackoverflow.com/questions/56364464/ ...
Brian Burns
To była dla mnie najprostsza odpowiedź. Pracował w 100%. Dzięki!
robrecord
17

Chrome specjalnie blokuje dostęp do plików lokalnych w ten sposób ze względów bezpieczeństwa.

Oto obejście umożliwiające włączenie flagi w przeglądarce Chrome (i otwarcie systemu na luki w zabezpieczeniach):

c: \ Pliki programów (x86) \ google \ chrome \ Application \ chrome.exe --allow-file-access-from-files

Scott
źródło
4
Próbowałem zastosować rozwiązanie „c: \ path \ chrome.exe” -allow-file-access-from-files, ale nie mogę go otworzyć. Przetestuj tę witrynę internetową fiddle.jshell.net/q326vLya/3 . Co ja robię źle?
KBH
9
Na GoogleChrome 66 nie działa. Chrome zaczyna się od tej flagi, ale nadal pokazuje, że nie można otworzyć pliku lokalnego.
Radon8472
9

Istnieje obejście problemu przy użyciu serwera internetowego dla przeglądarki Chrome .
Oto kroki:

  1. Dodaj rozszerzenie do Chrome.
  2. Wybierz folder (C: \ images) i uruchom serwer na wybranym porcie.

Teraz łatwo uzyskaj dostęp do lokalnego pliku:

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: Może być konieczne wybranie opcji nagłówka CORS w ustawieniach zaawansowanych, jeśli napotkasz błąd dostępu do innych źródeł.

Shwetabh Shekhar
źródło
6

Nie będziesz mógł załadować obrazu poza katalogiem projektu lub z katalogu na poziomie użytkownika, stąd ostrzeżenie „nie można uzyskać dostępu do zasobów lokalnych”.

Ale gdybyś umieścił plik w folderze głównym projektu, tak jak w programie {rootFolder}\Content\my-image.jpgi odnosił się do niego w następujący sposób:

<img src="/Content/my-image.jpg" />
PontiusTheBarbarian
źródło
5

Ten problem pojawia się, gdy używam PHP jako języka po stronie serwera, a obejściem było wygenerowanie kodowania base64 mojego obrazu przed wysłaniem wyniku do klienta

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

Myślę, że może dać komuś pomysł na stworzenie własnej pracy

Dzięki

Ruberandinda Patience
źródło
2

Google Chrome nie pozwala na ładowanie zasobów lokalnych ze względu na bezpieczeństwo. Chrome potrzebuje adresu URL http. Internet Explorer i Edge umożliwiają ładowanie zasobów lokalnych, ale Safari, Chrome i Firefox nie pozwalają na ładowanie zasobów lokalnych.

Przejdź do lokalizacji pliku i stamtąd uruchom serwer Python.

python -m SimpleHttpServer

następnie umieść ten adres URL w funkcji:

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);
}
szach w persji
źródło
2

Jeśli masz zainstalowane php - możesz skorzystać z wbudowanego serwera. Po prostu otwórz docelowy katalog z plikami i uruchom

php -S localhost:8001
Andrew Zhilin
źródło
1

Gdybyś mógł to zrobić, stanowiłoby to duży problem z bezpieczeństwem, ponieważ możesz uzyskać dostęp do swojego systemu plików i potencjalnie działać na dostępnych tam danych ... Na szczęście nie można zrobić tego, co próbujesz zrobić.

Jeśli potrzebujesz dostępu do lokalnych zasobów, możesz spróbować uruchomić serwer WWW na swoim komputerze, w takim przypadku Twoja metoda zadziała. Możliwe są inne obejścia, takie jak działanie w ustawieniach Chrome, ale zawsze wolę czysty sposób, instalując lokalny serwer WWW, może na innym porcie (nie, to nie jest takie trudne!).

Zobacz też:

Prak
źródło
powód reguły jest bardziej społeczny niż techniczny; przeglądarki wykonują dobrą robotę, zapobiegając programowemu dostępowi do zasobów spoza domeny (np. SOP, skrypty CDN, głęboko powiązane tagi IMG itp.), ale przeraża ludzi, widząc ich lokalną zawartość w oknie przeglądarki, nawet jeśli skrypt nie może powiedzieć, co pokazuje ...
dandavis
1
@dandavis tak, masz rację, nadal uważam, że zapobieganie temu może być dobre. Oprócz błędów w niektórych implementacjach (jeśli nie możesz otworzyć lokalnego zasobu, prawdopodobnie jesteś bezpieczniejszy), mogą istnieć określone scenariusze, w których inne osoby patrzą na Twój ekran (aplikacje do udostępniania ekranu lub po prostu za Twoimi plecami w biurze ) i nie chcesz, aby Twoje obrazy (potencjalnie karta kredytowa lub prywatny obraz) można było otwierać, odwiedzając tylko niektóre witryny internetowe, które mogą odgadnąć lokalizację w lokalnym systemie plików ...
Prak
1

Wystarczy zamienić wszystkie ścieżki sieciowe obrazu na ciągi bajtów w przechowywanym zakodowanym ciągu HTML. W tym celu potrzebujesz HtmlAgilityPack, aby przekonwertować ciąg HTML na dokument HTML. https://www.nuget.org/packages/HtmlAgilityPack

Znajdź poniższy kod, aby przekonwertować każdą ścieżkę sieciową src obrazu (lub ścieżkę lokalną) na żądane bajty. Z pewnością wyświetli wszystkie obrazy ze ścieżką sieciową (lub ścieżką lokalną) w IE, Chrome i 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;
Maishidh Mandviwala
źródło
1

Chrome i inne przeglądarki ograniczają dostęp serwera do plików lokalnych ze względów bezpieczeństwa. Możesz jednak otworzyć przeglądarkę w trybie dozwolonego dostępu. Po prostu otwórz terminal i przejdź do folderu, w którym jest przechowywany chrome.exe, i wpisz następujące polecenie.

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

Przeczytaj to, aby uzyskać więcej informacji

W ten sposób jednak nie zadziałało dla mnie, więc stworzyłem inną trasę dla każdego pliku w określonym katalogu. Dlatego przejście do tej ścieżki oznaczało otwarcie tego pliku.

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

Nazwałem tę funkcję, przekazując listę nazw plików w katalogu __dirname/public/extractedi utworzyła inną trasę dla każdej nazwy pliku, którą byłem w stanie wyświetlić po stronie serwera.

Tanmay_Gupta
źródło
0

To rozwiązanie działało dla mnie w PHP. Otwiera plik PDF w przeglądarce.

// $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);
    }
}
rgoot
źródło
0

Napotkałem ten problem, a oto moje rozwiązanie dla Angulara, opakowałem folder zasobów mojego Angulara w funkcję encodeURIComponent (). Zadziałało. Mimo to chciałbym dowiedzieć się więcej o ryzyku związanym z tym rozwiązaniem, jeśli istnieje:

`` `` 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```
wimblywombly
źródło