【问题标题】:Cannot open local file - Chrome: Not allowed to load local resource无法打开本地文件 - Chrome:不允许加载本地资源
【发布时间】:2016-12-24 17:42:27
【问题描述】:

测试浏览器: 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> 访问本地资源

标签: javascript google-chrome window.open


【解决方案1】:

我们在课堂上经常使用 Chrome,并且必须使用本地文件。

我们一直使用的是“Web Server for Chrome”。您启动它,选择希望使用的文件夹并转到 URL(例如您选择的 127.0.0.1:port)

这是一个简单的服务器,不能使用 PHP,但对于简单的工作,可能是您的解决方案:

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

【讨论】:

  • 伍迪:非常感谢!这种方法帮助了我。我在 Windows 10 上运行本地 Tomcat + 本地 AWS S3 存储桶。现在我可以在实时 AWS 服务器和本地服务器之间切换。干杯。问
  • 感谢伍迪,但你知道什么更好的吗?每次都需要吃午饭。我想要一些后台被动扩展,只允许访问 file:///
  • @Mohammad_Hosein 不幸的是,我不知道更简单的 chrome 插件。很多学生使用 EasyPHP Dev easyphp.org。还有 lite-server 用于更倾向于技术的github.com/johnpapa/lite-server | freecodecamp.org/news/…
  • 很好的解决方案,但我不确定它是否安全。据我所知,使用计算机作为服务器总是有风险的。
  • @john-c-j 除非您允许访问您的本地计算机,否则没有任何危害。您正在使用具有本地端口的计算机。如果你将本地端口暴露给外界,那么你就犯了一个巨大的错误。
【解决方案2】:

1) 打开终端并输入

npm install -g http-server

2) 转到您要为您提供文件的根文件夹并键入:

http-server ./

3) 阅读终端的输出,会出现类似http://localhost:8080 的东西。

那里的一切都将被允许获得。 示例:

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

【讨论】:

  • http-server 现在有一个导致错误的问题 - 您可以将其降级到 0.9 以进行修复 - 请参阅 stackoverflow.com/questions/56364464/…
  • 这对我来说是最简单的答案。工作100%。谢谢!
【解决方案3】:

好的,伙计们,我完全理解此错误消息背后的安全原因,但有时,我们确实需要一种解决方法......这是我的。它使用 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>

解决方案是用这段代码替换那些 &lt;a href..&gt; 元素,在我的 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: 驱动器。所以你能做的最好的就是使用像我这样的代码来访问网络驱动器上某处的文件。

【讨论】:

  • 听起来不错,但是您如何处理授权(读取权限)?如果不允许所有用户查看给定文件怎么办?您不需要以请求用户的名义执行读取吗?
  • 为什么要使用webclient打开本地文件?对我来说,它会尝试打开 C:\SomeNetworkPath\...
  • 如果我们不使用 angular 是否还有可能?
  • 这是一个有用的答案,但如果您通过这个 ashx 句柄像这样渲染和下载数百张图片,它会极大地影响网页的加载时间。
  • @Marie - 感谢您的反馈。真的,从来没有人有礼貌地解释为什么他们以前不赞成我,所以我很感激。我同意,它确实为 Chrome 的安全性提供了一个后门,但在我公司的内部应用程序中,这个解决方案是必要的,而且是救命稻草。但是,是的,正如我所说...小心行事!
【解决方案4】:

出于安全原因,Chrome 会以这种方式专门阻止本地文件访问。

这里有一篇文章可以解决 Chrome 中的标志问题(并让您的系统面临漏洞):

http://www.chrome-allow-file-access-from-file.com/

【讨论】:

  • 我试图遵循解决方案 "c:\path\chrome.exe" -allow-file-access-from-files 但我无法打开它。请测试本网站fiddle.jshell.net/q326vLya/3。我做错了什么?
  • 在 GoogleChrome 66 上它不起作用。 Chrome 以该标志开头,但仍显示无法打开本地文件。
  • 请编辑答案。它不再工作了。
【解决方案5】:

有一个使用Web Server for Chrome 的解决方法。
步骤如下:

  1. 将扩展添加到 chrome。
  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 选项,以防遇到任何跨源访问错误。

【讨论】:

  • 谢谢。但你知道更好的吗?每次都需要吃午饭。我想要一些只允许访问 file:/// 的后台被动扩展
【解决方案6】:

您将无法在项目目录之外或从用户级目录加载图像,因此会出现“无法访问本地资源警告”。

但是,如果您要将文件放在项目的根文件夹中,例如 {rootFolder}\Content\my-image.jpg,并像这样引用它:

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

【讨论】:

  • 网站的根文件夹在哪里?如何找到它?
【解决方案7】:

当我使用 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);

我认为可能会给某人一些想法来创建自己的作品

谢谢

【讨论】:

    【解决方案8】:

    出于安全考虑,Google Chrome 不允许加载本地资源。 Chrome 需要 http 网址。 Internet Explorer 和 Edge 允许加载本地资源,但 Safari、Chrome 和 Firefox 不允许加载本地资源。

    转到文件位置并从那里启动 Python 服务器。

    python -m SimpleHttpServer

    然后将该网址放入函数中:

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

    【讨论】:

    • 或者,对于 Python 3,python -m http.server
    【解决方案9】:

    如果你能做到这一点,这将代表一个大的安全问题,因为你可以访问你的文件系统,并可能对那里的可用数据采取行动......幸运的是,你无法做到你想做的事情。

    如果您需要访问本地资源,您可以尝试在您的机器上启动一个 Web 服务器,在这种情况下您的方法将起作用。其他解决方法是可能的,例如对 Chrome 设置进行操作,但我总是更喜欢干净的方式,安装本地 Web 服务器,可能在不同的端口上(不,这并不难!)。

    另见:

    【讨论】:

    • 该规则的原因更多的是社交而非技术;浏览器已经很好地防止了对域外资源的编程访问(例如 SOP、CDN 脚本、深度链接的 IMG 标签等),但它让人们害怕查看他们的本地内容一个浏览器窗口,即使脚本无法分辨它正在显示什么......
    • @dandavis 是的,你是对的,但我仍然相信防止这种情况发生是件好事。除了某些实现中的错误(如果您无法打开本地资源,您可能会更安全),可能还有一些特定情况下其他人正在查看您的屏幕(屏幕共享应用程序,或者只是在您的办公室背后) 并且您不希望您的图像(可能是信用卡或私人图像)可以通过访问一些可以猜测本地文件系统位置的网站来打开...
    【解决方案10】:

    如果您安装了 php - 您可以使用内置服务器。只需打开带有文件的目标目录并运行

    php -S localhost:8001
    

    【讨论】:

      【解决方案11】:

      您只需将所有图像网络路径替换为存储的编码 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;
      

      【讨论】:

        【解决方案12】:

        出于安全原因,Chrome 和其他浏览器会限制服务器对本地文件的访问。但是,您可以在允许的访问模式下打开浏览器。只需打开终端,进入 chrome.exe 所在的文件夹,编写以下命令即可。

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

        Read this for more details

        但是,这种方式对我不起作用,因此我为特定目录中的每个文件创建了不同的路径。因此,转到该路径意味着打开该文件。

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

        我调用了这个函数,传递了目录__dirname/public/extracted 中的文件名列表,它为我能够在服务器端呈现的每个文件名创建了不同的路由。

        【讨论】:

          【解决方案13】:

          这个解决方案在 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);
              }
          }
          

          【讨论】:

            【解决方案14】:

            我遇到了这个问题,这是我的 Angular 解决方案,我将 Angular 的资产文件夹包装在 encodeURIComponent() 函数中。有效。但是,如果有的话,我想更多地了解这个解决方案的风险:

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

            I used Angular 9, so this is my url when I clicked open local file:
            ```http://localhost:4200/%2Fassets%2Foffice%2Ffile_2.pdf```
            

            【讨论】:

              【解决方案15】:

              在音频文件的情况下,当您提供&lt;audio src="C://somePath"/&gt; 时,这会引发错误提示cannot load local resource. 这是有道理的,因为任何网页都不能简单地提供本地路径并访问您的私人文件。

              如果您尝试使用动态路径播放音频,通过 JS 更改 src property,那么这里是使用 Flask 服务器和 HTML 的示例实现。

              server.py

              @app.route("/")
                  def home():
                      return render_template('audioMap.html')
              
              @app.route('/<audio_file_name>')
              def view_method(audio_file_name):
                  path_to_audio_file = "C:/Audios/yourFolderPath" + audio_file_name
                  return send_file(
                       path_to_audio_file, 
                       mimetype="audio/mp3", 
                       as_attachment=True, 
                       attachment_filename="test.mp3")
              

              audioMap.html

              {% raw %}
              <!DOCTYPE html>
              <html>
              <body>
                  AUDIO: <audio src="Std.mp3" controls  >
              </body>
              </html>
              {% endraw %}
              

              解释:

              当您在src 属性下提供音频文件名时,这会在烧瓶中创建一个获取请求,如图所示

              127.0.0.1 - - [04/May/2021 21:33:12] "GET /Std.mp3 HTTP/1.1" 200 -
              

              如您所见,flask 已经发送了对Std.mp3 文件的Get 请求。因此,为了服务这个 get 请求,我们编写了一个端点,它获取音频文件名,从本地目录中读取它,然后返回它。因此音频会显示在 UI 上。

              注意:这仅在您使用 通过烧瓶渲染模板方法,或者说,使用烧瓶作为您的网络服务器。

              【讨论】:

                【解决方案16】:

                这是给google-chrome-extension

                const url = "file:///C:\002.jpg"
                chrome.tabs.create({url, active:true})
                

                manifest.json

                {
                  "name": "",
                  "manifest_version": 3,
                  "permissions": [
                    "activeTab",
                    "tabs"
                  ],
                  // ...
                }
                
                

                【讨论】:

                  猜你喜欢
                  • 2021-09-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2018-03-16
                  • 1970-01-01
                  • 2016-10-08
                  • 2016-11-04
                  相关资源
                  最近更新 更多