chrome打開本地鏈接


同事之前給我提了一個需求,想實現在網頁里點擊鏈接地址后直接打開指定的地址(路徑是內網共享的目錄,file://share.xx.com\x\x)。


瀏覽器因為有安全的限制,是無法訪問 web 頁面時,可以打開本地PC的目錄。當你點擊帶有本地文件鏈接的超鏈接(file://),控制台上會報錯:Not allowed to load local resource:


最開始在網上搜索了一下,有二個插件看上去似乎可以滿足需求。

(1)Enable local file links

(2)Local Explore – File Manager on web browser


image

插件啟用后,類似下面這種效果(跟他們想要的效果還是有區別)。

image


Local Explore,自定義了協議,然后呼起本地 exe,再打開資源管理器,是期望的效果。但是它最大的問題是:如果路徑有中文,就亂碼,無法正常使用。


它的原理倒是比較簡單,修改超鏈接為 LocalExplore:file://xxxx,如果注冊表添加了對該協議的監聽,當瀏覽器訪問該協議時,會觸發指定的 exe 並傳入相關的參數。


我要解決亂碼問題,先處理瀏覽器擴展插件,再就是替換 exe 的實現就可以了。

image


(1)替換插件,解決因插件 escape 導致的亂碼問題(注:不太能理解作者為啥要用 JSON.parse 處理一下)

對比了二個插件的實現,我准備在 Local Explore 插件的基礎上進行精簡。只留下必要的代碼,然后通過開發者模式,加載進 chrome 的擴展程序里。

image

background.js 里的代碼被我刪光了,content.js 只進行一個操作,遍歷文檔所有超鏈接,然后修改其 href 屬性。

$(document).ready(function() {
    var optOpenFolders = "true";
    var protocolStr = "LocalExplorer:";

    // var clickEventHandler = function(evt) {
    //     evt.preventDefault();

    //     chrome.extension.sendMessage({
    //         cmd: "click",
    //         data: this.href
    //     });
    // };

    $("a").each(function(i, e) {
        if (e.href !== undefined && e.href !== null && e.href !== "") {
            if (!e.href.match(/^file:\/\//)) {
                return;
            }

            if (e.href.match(/^file:\/\//)) {
                if (window.debug) console.log(e.href);

                e.href = protocolStr + e.href;
                if (e.target) e.target = "_self";
            }
            // $(e).off("click", clickEventHandler);
            // $(e).on("click", clickEventHandler);
        }
    });
});


manifest.json 也做了一點修改

{
    "update_url": "https://clients2.google.com/service/update2/crx",
    "version": "2021.7.6",
    "short_name": "Meteoric Local Explorer",
    "name": "Meteoric Local Explorer - File Manager on web browser",
    "description": "__MSG_extDescription__",
    "default_locale": "zh_CN",
    "icons": {
        "128": "icon/icon128.png",
        "32": "icon/icon32.png",
        "16": "icon/icon16.png"
    },
    "browser_action": {
        "default_icon": "icon/icon32.png",
        "default_title": "Meteoric Local Explorer"
    },
    "content_scripts": [{
        "matches": ["<all_urls>"],
        "js": ["jquery.js", "content.js"],
        "all_frames": false,
        "run_at": "document_start"
    }],
    "background": {
        "scripts": ["background.js"]
    },
    "options_page": "", // options.html
    "permissions": [
        "http://*/*",
        "https://*/*",
        "tabs"
    ],
    "manifest_version": 2
}


(2)替換 exe,支持打開中文鏈接

這里我直接用 C# 簡單寫了一個 exe,實現了基本的功能。為了精簡 Release 版本生成的內容,我對幾處設置作了簡單的調整

(1)項目屬性里面的,生成 –> 高級 –> 高級生成設置,輸出 –> 調試信息,選擇無,避免生成 pdb 文件;

(2)App.config 的文件屬性,修改‘生成操作’為‘嵌入的資源’,避免生成  *.exe.config 文件;


這樣生成的 Release 目錄就是比較干凈的了,只有一個叫 LocalExplorer.exe 的文件。替換掉安裝在 C 盤里面的 exe(默認路徑在:"C:\Program Files (x86)\LocalExplorer\LocalExplorer.exe" )

using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace FriendTimesLocalExplorer { class Program { static void Main(string[] args) { /* for (int i = 0, len = args.Length; i < len; i++) { // Get first param } */ if (args.Length < 1) { MessageBox.Show("File Path is Empty", "System Tips", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } string filePath = args[0]; // escape filePath = Uri.UnescapeDataString(filePath).Replace("/", "\\"); // delete protocol filePath = filePath.Replace("localexplorer:", ""); filePath = filePath.Replace("file:", "");

// get right file path filePath = filePath.Substring(filePath.IndexOf('\\')); //Console.WriteLine(filePath); if (Directory.Exists(filePath) || File.Exists(filePath)) { Process p = new Process(); p.StartInfo.FileName = "explorer.exe"; p.StartInfo.CreateNoWindow = true; p.StartInfo.UseShellExecute = false; // hidden p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; p.EnableRaisingEvents = true; p.StartInfo.RedirectStandardError = true; if (File.Exists(filePath)) { p.StartInfo.Arguments = @"/select," + filePath; } else { p.StartInfo.Arguments = filePath; } try { p.Start(); // explorer.exe 異常結束時,會導致啟動不斷重啟 p.WaitForExit(); if (p != null) { p.Close(); p.Dispose(); p = null; } } catch (Exception e) { MessageBox.Show(e.ToString(), "System error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } else { MessageBox.Show("Not Found Path : \n" + filePath, "System error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } } }


瀏覽器插件 和 exe 都進行替換后,就能實現點擊鏈接調用本地exe,再通過 exe 打開指定的目錄了。迅雷、QQ或其它客戶端軟件,基本上也是使用類似的原理,實現點擊網頁鏈接呼起本地的客戶端應用程序(應用程序想干嘛就自己實現)


注意點擊時,會彈出一個提示。

image


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM