Não é possível abrir o arquivo local - Chrome: não tem permissão para carregar o recurso local

99

Navegador de teste: Versão do Chrome: 52.0.2743.116

É um javascript simples que serve para abrir um arquivo de imagem local como 'C: \ 002.jpg'

function run(){

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

   window.open(URL, null);

}
run();

Aqui está meu código de exemplo. https://fiddle.jshell.net/q326vLya/3/

Por favor, me dê sugestões adequadas.

KBH
fonte
use <input type=file>para obter acesso a recursos locais
dandavis

Respostas:

62

Sei que isso é meio antigo, mas vejo muitas perguntas como essa ...

Usamos muito o Chrome na sala de aula e é fundamental trabalhar com arquivos locais.

O que temos usado é o "Servidor Web para Chrome". Você o inicia, escolhe a pasta com a qual deseja trabalhar e vai para o URL (como 127.0.0.1:port que você escolheu)

É um servidor simples e não pode usar PHP, mas para um trabalho simples, pode ser sua solução:

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

Woody
fonte
1
Woody: muito obrigado! Essa abordagem me ajudou. Eu executo um Tomcat local + um bucket AWS S3 local no Windows 10. Agora posso alternar entre o servidor AWS ao vivo e um local. Felicidades. Q
user1723453
20

Ok pessoal, eu entendo completamente os motivos de segurança por trás dessa mensagem de erro, mas às vezes, precisamos de uma solução alternativa ... e aqui está a minha. Ele usa ASP.Net (em vez de JavaScript, no qual esta pergunta foi baseada), mas espero que seja útil para alguém.

Nosso aplicativo interno tem uma página da web onde os usuários podem criar uma lista de atalhos para arquivos úteis espalhados por nossa rede. Quando eles clicam em um desses atalhos, queremos abrir esses arquivos ... mas é claro, o erro do Chrome impede isso.

insira a descrição da imagem aqui

Esta página da web usa AngularJS 1.x para listar os vários atalhos.

Originalmente, minha página da web estava tentando criar diretamente um <a href..>elemento apontando para os arquivos, mas isso produziu o Not allowed to load local resourceerro " " quando um usuário clicou em um desses links.

<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 solução foi substituir esses <a href..>elementos por este código, para chamar uma função no meu controlador Angular ...

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

A função em si é muito simples ...

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

E em meu projeto ASP.Net, adicionei um arquivo Handler chamado DownloadExternalFile.aspxque continha este código:

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

E é isso.

Agora, quando um usuário clica em um dos meus links de atalho, ele chama a OpenAnExternalFilefunção, que abre esse arquivo .ashx, passando o caminho + nome do arquivo que queremos abrir.

Este código do manipulador carrega o arquivo e, em seguida, passa seu conteúdo de volta na resposta HTTP.

E, trabalho feito, a página da Web abre o arquivo externo.

Ufa! Novamente - há uma razão pela qual o Chrome lança essa Not allowed to load local resourcesexceção " ", então tenha cuidado com isso ... mas estou postando este código apenas para demonstrar que esta é uma maneira bastante simples de contornar essa limitação.

Só um último comentário: a pergunta original queria abrir o arquivo " C:\002.jpg". Você não pode fazer isso. Seu site ficará em um servidor (com sua própria unidade C:) e não terá acesso direto à unidade C: do seu usuário. Portanto, o melhor que você pode fazer é usar um código como o meu para acessar arquivos em algum lugar em uma unidade de rede.

Mike Gledhill
fonte
Parece bom, mas como você lida com a autorização (permissões de leitura)? E se nem todos os usuários têm permissão para ver um determinado arquivo? Você não precisaria realizar a leitura no nome do usuário solicitante?
Timi de
Por que você usa um cliente da web para abrir um arquivo local? E para mim, ele tenta abrir C: \ SomeNetworkPath \ ...
Kev
Se não estivermos usando angular, ainda é possível?
Ahmad.Tr
Esta foi uma resposta útil, mas afetaria muito o tempo de carregamento da página da web se você tivesse centenas de imagens sendo renderizadas e baixadas dessa forma por meio deste identificador ashx.
Jamshaid Kamran
17

O Chrome bloqueia especificamente o acesso a arquivos locais dessa forma por motivos de segurança.

Esta é uma solução alternativa para habilitar o sinalizador no Chrome (e abrir seu sistema para vulnerabilidades):

c: \ Arquivos de programas (x86) \ google \ chrome \ Application \ chrome.exe --allow-file-access-from-files

Scott
fonte
4
Tentei seguir a solução "c: \ path \ chrome.exe" -allow-file-access-from-files mas não consigo abri-la. Teste este site fiddle.jshell.net/q326vLya/3 . O que estou fazendo de errado?
KBH de
5
No GoogleChrome 66 não está funcionando. O Chrome começa com essa bandeira, mas ainda mostra que o arquivo local não pode ser aberto.
Radon8472
16

1) Abra seu terminal e digite

npm install -g http-server

2) Vá para a pasta raiz em que deseja fornecer os arquivos e digite:

http-server ./

3) Leia a saída do terminal, algo meio http://localhost:8080que aparecerá.

Tudo lá será permitido ser obtido. Exemplo:

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

Alex
fonte
http-server tem um problema que está causando erros - você pode fazer o downgrade para 0.9 para corrigir - consulte stackoverflow.com/questions/56364464/…
Brian Burns
Esta foi a resposta mais simples para mim. Trabalhou 100%. Obrigado!
robrecord de
9

Existe uma solução alternativa para o uso do Web Server para Chrome .
Aqui estão as etapas:

  1. Adicione a extensão ao cromo.
  2. Escolha a pasta (C: \ imagens) e inicie o servidor na porta desejada.

Agora acesse facilmente seu arquivo local:

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: Você pode precisar selecionar a opção CORS Header na configuração avançada caso você enfrente qualquer erro de acesso de origem cruzada.

Shwetabh Shekhar
fonte
5

Você não poderá carregar uma imagem fora do diretório do projeto ou de um diretório de nível de usuário, portanto, o "aviso de recurso local não pode ser acessado".

Mas se você colocasse o arquivo em uma pasta raiz de seu projeto como em {rootFolder}\Content\my-image.jpge referenciasse assim:

<img src="/Content/my-image.jpg" />
Pôncio TheBarbarian
fonte
4

Esse problema surge quando estou usando PHP como linguagem do lado do servidor e a solução alternativa era gerar codificação base64 da minha imagem antes de enviar o resultado ao cliente

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

Acho que pode dar a alguém a ideia de criar seu próprio trabalho em torno

obrigado

Paciência Ruberandinda
fonte
2

O Google Chrome não permite carregar recursos locais por causa da segurança. O Chrome precisa de um url http. Internet Explorer e Edge permitem carregar recursos locais, mas Safari, Chrome e Firefox não permitem carregar recursos locais.

Vá para o local do arquivo e inicie o servidor Python a partir daí.

python -m SimpleHttpServer

em seguida, coloque esse url em funcionamento:

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

fonte
2

Se você tiver o php instalado - você pode usar o servidor embutido. Basta abrir o diretório de destino com os arquivos e executar

php -S localhost:8001
Andrew Zhilin
fonte
1

Se você pudesse fazer isso, isso representaria um grande problema de segurança, pois você pode acessar seu sistema de arquivos e, potencialmente, agir sobre os dados disponíveis nele ... Felizmente não é possível fazer o que você está tentando fazer.

Se você precisa que recursos locais sejam acessados, você pode tentar iniciar um servidor web em sua máquina e, neste caso, seu método funcionará. Outras soluções alternativas são possíveis, como atuar nas configurações do Chrome, mas eu sempre prefiro o caminho limpo, instalando um servidor web local, talvez em uma porta diferente (não, não é tão difícil!).

Veja também:

Prak
fonte
a razão da regra é mais social do que técnica; navegadores fazem um bom trabalho em prevenir o acesso programático a recursos fora do domínio (por exemplo, SOP, scripts CDN, tags IMG com links profundos, etc), mas assusta as pessoas ao ver seu conteúdo local em uma janela do navegador, mesmo que o o script não consegue dizer o que está mostrando ...
dandavis
1
@dandavis sim, você tem razão, ainda acredito que pode ser bom evitar que isso aconteça. Além de bugs em algumas implementações (se você não pode abrir um recurso local, provavelmente está mais seguro), pode haver alguns cenários específicos onde outras pessoas estão olhando para sua tela (aplicativos de compartilhamento de tela ou simplesmente nas costas do seu escritório ) e você não quer que suas imagens (potencialmente um cartão de crédito ou uma imagem privada) possam ser abertas apenas visitando alguns sites que podem adivinhar a localização em seu sistema de arquivos local ...
Prak
1

Você só precisa substituir todos os caminhos de rede da imagem por strings de bytes na string HTML codificada armazenada. Para isso, é necessário HtmlAgilityPack para converter string Html em documento Html. https://www.nuget.org/packages/HtmlAgilityPack

Encontre o código abaixo para converter cada caminho de rede src de imagem (ou caminho local) em sting de bytes. Definitivamente, ele exibirá todas as imagens com caminho de rede (ou caminho local) no IE, chrome e 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
fonte
0

Essa solução funcionou para mim em PHP. Ele abre o PDF no navegador.

// $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
fonte
0

O Chrome e outros navegadores restringem o acesso de um servidor a arquivos locais por motivos de segurança. No entanto, você pode abrir o navegador no modo de acesso permitido. Basta abrir o terminal e ir para a pasta onde o chrome.exe está armazenado e escrever o seguinte comando.

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

Leia isto para mais detalhes

Dessa forma, no entanto, não funcionou para mim, então fiz uma rota diferente para cada arquivo em um diretório específico. Portanto, ir para esse caminho significava abrir esse arquivo.

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

Eu chamei esta função passando a lista de nome de arquivo no diretório __dirname/public/extractede ela criou uma rota diferente para cada nome de arquivo que fui capaz de renderizar no lado do servidor.

Tanmay_Gupta
fonte
0

Encontrei esse problema e aqui está minha solução para o Angular, envolvi a pasta de ativos do Angular na função encodeURIComponent (). Funcionou. Mesmo assim, gostaria de saber mais sobre o risco desta solução, se houver:

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