ไม่สามารถเปิดไฟล์ในเครื่อง - Chrome: ไม่อนุญาตให้โหลดทรัพยากรในเครื่อง


108

ทดสอบเบราว์เซอร์: เวอร์ชันของ Chrome: 52.0.2743.116

มันเป็นจาวาสคริปต์ง่ายๆที่จะเปิดไฟล์รูปภาพจากโลคัลเช่น '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

คำตอบ:


66

รู้ว่าเก่า แต่เจอคำถามแบบนี้ ...

เราใช้ Chrome เป็นจำนวนมากในชั้นเรียนและจำเป็นต้องทำงานกับไฟล์ในเครื่อง

สิ่งที่เราใช้คือ "เว็บเซิร์ฟเวอร์สำหรับ Chrome" คุณเริ่มต้นใช้งานเลือกโฟลเดอร์ที่ต้องการใช้งานและไปที่ URL (เช่น 127.0.0.1:port ที่คุณเลือก)

มันเป็นเซิร์ฟเวอร์ที่เรียบง่ายและไม่สามารถใช้ PHP ได้ แต่สำหรับงานง่ายๆอาจเป็นวิธีแก้ปัญหาของคุณ:

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


1
วู้ดดี้: ขอบคุณมาก! แนวทางนี้ช่วยฉันได้ ฉันเรียกใช้ Tomcat ในเครื่อง + ที่เก็บข้อมูล AWS S3 ในเครื่องบน Windows 10 ตอนนี้ฉันสามารถสลับไปมาระหว่างเซิร์ฟเวอร์ AWS สดกับเซิร์ฟเวอร์ภายในเครื่องได้ ไชโย Q
user1723453

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..>องค์ประกอบเหล่านั้นด้วยรหัสนี้เพื่อเรียกใช้ฟังก์ชันในตัวควบคุมเชิงมุมของฉัน ...

<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ฟังก์ชันนี้ซึ่งจะเปิดไฟล์. asx นี้โดยส่งผ่านเส้นทาง + ชื่อไฟล์ของไฟล์ที่เราต้องการเปิด

โค้ดตัวจัดการนี้จะโหลดไฟล์จากนั้นส่งเนื้อหากลับไปในการตอบสนอง HTTP

และเมื่องานเสร็จแล้วหน้าเว็บจะเปิดไฟล์ภายนอก

ฟิ้ว! อีกครั้ง - มีเหตุผลว่าทำไม Chrome จึงโยนNot allowed to load local resourcesข้อยกเว้น "" นี้ออกไปดังนั้นควรระมัดระวังในเรื่องนี้ ... แต่ฉันโพสต์รหัสนี้เพื่อแสดงให้เห็นว่านี่เป็นวิธีที่ค่อนข้างง่ายสำหรับข้อ จำกัด นี้

เพียงความคิดเห็นสุดท้าย: คำถามเดิมต้องการเปิดไฟล์ " C:\002.jpg" คุณไม่สามารถทำสิ่งนี้ได้ เว็บไซต์ของคุณจะนั่งบนเซิร์ฟเวอร์เดียว (โดยมีไดรฟ์ C: เป็นของตัวเอง) และไม่มีการเข้าถึงไดรฟ์ C: ของผู้ใช้โดยตรง ดังนั้นสิ่งที่ดีที่สุดที่คุณทำได้คือใช้รหัสเหมือนของฉันเพื่อเข้าถึงไฟล์ที่ใดที่หนึ่งบนไดรฟ์เครือข่าย


ฟังดูดี แต่คุณจะจัดการการอนุญาต (อ่านสิทธิ์) อย่างไร จะเกิดอะไรขึ้นหากผู้ใช้บางคนไม่ได้รับอนุญาตให้ดูไฟล์ที่ระบุ คุณไม่จำเป็นต้องทำการอ่านในนามของผู้ใช้ที่ร้องขอหรือ?
Timi

เหตุใดคุณจึงใช้ Webclient เพื่อเปิดไฟล์ในเครื่อง และสำหรับฉันมันพยายามเปิด C: \ SomeNetworkPath \ ...
Kev

ถ้าเราไม่ได้ใช้เชิงมุมจะเป็นไปได้หรือไม่?
Ahmad.Tr

นี่เป็นคำตอบที่มีประโยชน์ แต่จะมีผลอย่างมากต่อเวลาในการโหลดหน้าเว็บหากคุณมีการแสดงผลและดาวน์โหลดรูปภาพหลายร้อยภาพผ่านทางที่จับ ashx นี้
Jamshaid Kamran

17

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/…
Brian Burns

นี่เป็นคำตอบที่ง่ายที่สุดสำหรับฉัน ทำงานได้ 100% ขอบคุณ!
robrecord

17

Chrome บล็อกการเข้าถึงไฟล์ในเครื่องโดยเฉพาะด้วยเหตุผลด้านความปลอดภัย

นี่คือวิธีแก้ปัญหาในการเปิดใช้งานการตั้งค่าสถานะใน Chrome (และเปิดระบบของคุณจนถึงช่องโหว่):

c: \ Program Files (x86) \ google \ chrome \ Application \ chrome.exe - อนุญาตไฟล์เข้าถึงจากไฟล์


4
ฉันพยายามทำตามวิธีแก้ปัญหา "c: \ path \ chrome.exe" -allow-file-access-from-files แต่ฉันไม่สามารถเปิดได้ กรุณาทดสอบเว็บไซต์นี้fiddle.jshell.net/q326vLya/3 ผมทำอะไรผิดหรือเปล่า?
KBH

9
บน Google Chrome 66 ใช้งานไม่ได้ Chrome เริ่มต้นด้วยการตั้งค่าสถานะนั้น แต่ยังคงแสดงว่าไฟล์ในเครื่องสามารถเปิดได้
Radon8472

9

มีวิธีแก้ปัญหาโดยใช้เป็นเว็บเซิร์ฟเวอร์สำหรับ 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 จากการตั้งค่าขั้นสูงในกรณีที่คุณประสบข้อผิดพลาดในการเข้าถึงจุดเริ่มต้น


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 url Internet Explorer และ Edge อนุญาตให้โหลดทรัพยากรในเครื่อง แต่ Safari, Chrome และ Firefox ไม่อนุญาตให้โหลดทรัพยากรในเครื่อง

ไปที่ตำแหน่งไฟล์และเริ่มเซิร์ฟเวอร์ Python จากที่นั่น

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 - คุณสามารถใช้เซิร์ฟเวอร์ในตัวได้ เพียงเปิด dir เป้าหมายพร้อมไฟล์และเรียกใช้

php -S localhost:8001

1

หากคุณสามารถทำได้มันจะแสดงถึงปัญหาด้านความปลอดภัยที่ยิ่งใหญ่เนื่องจากคุณสามารถเข้าถึงระบบไฟล์ของคุณและอาจดำเนินการกับข้อมูลที่มีอยู่ในนั้น ... โชคดีที่ไม่สามารถทำสิ่งที่คุณพยายามทำได้

หากคุณต้องการเข้าถึงทรัพยากรในพื้นที่คุณสามารถลองเริ่มต้นเว็บเซิร์ฟเวอร์บนเครื่องของคุณและในกรณีนี้วิธีของคุณจะได้ผล วิธีแก้ปัญหาอื่น ๆ เป็นไปได้เช่นการดำเนินการกับการตั้งค่า Chrome แต่ฉันมักจะชอบวิธีที่สะอาดติดตั้งเว็บเซิร์ฟเวอร์ในตัวเครื่องอาจใช้พอร์ตอื่น (ไม่มันไม่ยากเลย!)

ดูสิ่งนี้ด้วย:


เหตุผลของกฎเป็นเรื่องทางสังคมมากกว่าทางเทคนิค เบราว์เซอร์ทำงานได้ดีในการป้องกันการเข้าถึงทรัพยากรนอกโดเมนแบบเป็นโปรแกรมอยู่แล้ว (เช่น SOP สคริปต์ CDN แท็ก IMG ที่ลิงก์ในรายละเอียด ฯลฯ ) แต่จะทำให้ผู้คนไม่เห็นเนื้อหาในเครื่องในหน้าต่างเบราว์เซอร์แม้ว่า สคริปต์ไม่สามารถบอกได้ว่ากำลังแสดงอะไร ...
dandavis

1
@dandavis ใช่คุณพูดถูก แต่ฉันเชื่อว่ามันเป็นการดีที่จะป้องกันไม่ให้สิ่งนี้เกิดขึ้น นอกเหนือจากข้อบกพร่องในการใช้งานบางอย่าง (หากคุณไม่สามารถเปิดทรัพยากรในพื้นที่ได้คุณอาจปลอดภัยกว่า) อาจมีสถานการณ์เฉพาะบางอย่างที่คนอื่นมองหน้าจอของคุณ (แอปแชร์หน้าจอหรือเพียงแค่อยู่ข้างหลังคุณในสำนักงานของคุณ ) และคุณไม่ต้องการให้ภาพของคุณ (อาจเป็นบัตรเครดิตหรือภาพส่วนตัว) สามารถเปิดได้เพียงแค่เข้าไปที่เว็บไซต์บางแห่งที่สามารถเดาตำแหน่งบนระบบไฟล์ในเครื่องของคุณได้ ...
Prak

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```
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.