【问题标题】:Is there a way of Creating lnk file using javascript有没有一种方法可以使用 javascript 创建 lnk 文件
【发布时间】:2014-10-01 09:15:20
【问题描述】:

我想让我网站中的用户能够下载“lnk”文件。 我的想法是生成这个文件以包含一个只能使用一次的地址。 有没有办法在javascript中生成这个文件? 流程类似于 -

  1. 用户按下按钮
  2. javascript 生成此文件并将其下载到用户的机器上
  3. 用户将此文件发送给另一个用户,以便在他的机器上使用这个一次性地址

这样的事情在客户端的 javascript 中是可行的吗?还是我需要使用 java 服务器端生成这个文件?

【问题讨论】:

  • @Cory 确实如此-查看Blob,您可以在 JS 中创建任意文件并将其下载到计算机。
  • @user1322801 这就是你的做法 - 不会很有趣。首先 - 阅读.lnk file format works Microsoft 是如何发布规范的。其次,使用 Blob 在 JavaScript 中写入二进制数据。最后将该 Blob 转换为适用于所有浏览器的下载,例如参见 this pagestackoverflow.com/questions/3665115/…
  • @TomSarduy 我不这么认为,因为它没有指定 如何 来准确地完成任何这些事情。它所做的只是为 OP(以及未来可能的答案)提供有关如何尝试解决问题的方向 - 答案应该是问题的实际解决方案(不是生产就绪,但至少在概念验证级别)。我认为概念验证大约需要 80 行代码(可能会少一点),如果您想拿起手套并实施它,那么无论谁编写它,都会赢得很高的声誉。
  • @BenjaminGruenbaum:OP 确实问过“可行吗?有没有办法在 JS 中生成文件?”而不是“如何创建 lnk 文件?”。您的评论确实回答了这个问题 - 我认为要求一个实际的解决方案会离题或过于宽泛。

标签: javascript html


【解决方案1】:

这是mslink.sh的忠实翻译。

我只在 Windows 8.1 中测试了我的答案,但我认为它也适用于旧版本的 Windows。

function create_lnk_blob(lnk_target) {
    function hex_to_arr(s) {
        var result = Array(s.length / 2);
        for (var i = 0; i < result.length; ++i) {
            result[i] = +('0x' + s.substr(2*i, 2));
        }
        return result;
    }

    function str_to_arr(s) {
        var result = Array(s.length);
        for (var i = 0; i < s.length; ++i) {
            var c = s.charCodeAt(i);
            if (c >= 128) {
                throw Error("Only ASCII paths are suppored :-(");
            }
            result[i] = c;
        }
        return result;
    }

    function convert_CLSID_to_DATA(s) {
        var idx = [[6,2], [4,2], [2,2], [0,2],
                   [11,2], [9,2], [16,2], [14,2],
                   [19,4], [24,12]];
        var s = idx.map(function (ii) {
            return s.substr(ii[0], ii[1]);
        });
        return hex_to_arr(s.join(''));
    }

    function gen_IDLIST(s) {
        var item_size = (0x10000 + s.length + 2).toString(16).substr(1);
        return hex_to_arr(item_size.replace(/(..)(..)/, '$2$1')).concat(s);
    }

    var HeaderSize = [0x4c, 0x00,0x00,0x00],
        LinkCLSID = convert_CLSID_to_DATA("00021401-0000-0000-c000-000000000046"),
        LinkFlags = [0x01,0x01,0x00,0x00], // HasLinkTargetIDList ForceNoLinkInfo

        FileAttributes_Directory = [0x10,0x00,0x00,0x00],
        FileAttributes_File = [0x20,0x00,0x00,0x00],

        CreationTime = [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],
        AccessTime = [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],
        WriteTime = [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],

        FileSize = [0x00,0x00,0x00,0x00],
        IconIndex = [0x00,0x00,0x00,0x00],
        ShowCommand = [0x01,0x00,0x00,0x00], //SW_SHOWNORMAL
        Hotkey = [0x00,0x00], // No Hotkey
        Reserved = [0x00,0x00],
        Reserved2 = [0x00,0x00,0x00,0x00],
        Reserved3 = [0x00,0x00,0x00,0x00],
        TerminalID = [0x00,0x00],

        CLSID_Computer = convert_CLSID_to_DATA("20d04fe0-3aea-1069-a2d8-08002b30309d"),
        CLSID_Network = convert_CLSID_to_DATA("208d2c60-3aea-1069-a2d7-08002b30309d"),

        PREFIX_LOCAL_ROOT = [0x2f],
        PREFIX_FOLDER = [0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],
        PREFIX_FILE = [0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],
        PREFIX_NETWORK_ROOT = [0xc3,0x01,0x81],
        PREFIX_NETWORK_PRINTER = [0xc3,0x02,0xc1],

        END_OF_STRING = [0x00];

    if (/.*\\+$/.test(lnk_target)) {
        lnk_target = lnk_target.replace(/\\+$/g, '');
        var target_is_folder = true;
    }

    var prefix_root, item_data, target_root, target_leaf;
    if (lnk_target.substr(0, 2) === '\\\\') {
        prefix_root = PREFIX_NETWORK_ROOT;
        item_data = [0x1f, 0x58].concat(CLSID_Network);
        target_root = lnk_target.subtr(lnk_target.lastIndexOf('\\'));
        if (/\\\\.*\\.*/.test(lnk_target)) {
            target_leaf = lnk_target.substr(lnk_target.lastIndexOf('\\') + 1);
        }
        if (target_root === '\\') {
            target_root = lnk_target;
        }
    } else {
        prefix_root = PREFIX_LOCAL_ROOT;
        item_data = [0x1f, 0x50].concat(CLSID_Computer);
        target_root = lnk_target.replace(/\\.*$/, '\\');
        if (/.*\\.*/.test(lnk_target)) {
            target_leaf = lnk_target.replace(/^.*?\\/, '');
        }
    }

    var prefix_of_target, file_attributes;
    if (!target_is_folder) {
        prefix_of_target = PREFIX_FILE;
        file_attributes = FileAttributes_File;
    } else {
        prefix_of_target = PREFIX_FOLDER;
        file_attributes = FileAttributes_Directory;
    }

    target_root = str_to_arr(target_root);
    for (var i = 1; i <= 21; ++i) {
        target_root.push(0);
    }

    var id_list_items = gen_IDLIST(item_data);
    id_list_items = id_list_items.concat(
            gen_IDLIST(prefix_root.concat(target_root, END_OF_STRING)));
    if (target_leaf) {
        target_leaf = str_to_arr(target_leaf);
        id_list_items = id_list_items.concat(
                gen_IDLIST(prefix_of_target.concat(target_leaf, END_OF_STRING)));
    }
    var id_list = gen_IDLIST(id_list_items);

    var data = [].concat(HeaderSize,
                         LinkCLSID,
                         LinkFlags,
                         file_attributes,
                         CreationTime,
                         AccessTime,
                         WriteTime,
                         FileSize,
                         IconIndex,
                         ShowCommand,
                         Hotkey,
                         Reserved,
                         Reserved2,
                         Reserved3,
                         id_list,
                         TerminalID);
    return new Blob([new Uint8Array(data)], { type: 'application/x-ms-shortcut' });
}

var blob = create_lnk_blob('C:\\Windows\\System32\\Calc.exe');

像这样使用它:

var blob_to_file = create_lnk_blob('C:\\Windows\\System32\\Calc.exe');
var blob_to_folder = create_lnk_blob('C:\\Users\\Myself\\Desktop\\'); // with a trailing slash

演示:http://jsfiddle.net/5cjgLyan/2/

【讨论】:

  • 这是我找到的最好的解决方案,但浏览器似乎讨厌 .lnk 文件(我也尝试在服务器端生成 lnk 文件)
  • @kay,这太棒了!但是如何向目标添加参数?
  • @datdinhquoc,对不起,我不知道。我只是转换了脚本而不理解它。
【解决方案2】:

如果您的网站允许使用 php,这将很简单。

如果您的脚本是 html 文件的一部分,只需编写 javascript,就像您编写它以发送静态 lnk 文件一样。然后,在 lnk 地址部分,将 javascript 拆分为两部分,拆分为 html。然后在这一点上,放入

<?php /*PHP code set a variable *? /* PHP code to generate proper string*/ PRINT /*PHP variable*/
?>

【讨论】:

    【解决方案3】:

    我认为让它成为纯客户端是不可能的。 即使是 web rtc 协议也需要至少一个 iceServer 来向其他客户端发送信号。

    我认为最简单的方法是使用http://peerjs.com/

    您可以先创建房间所有者的 clinet 令牌

    //room owner side
    peer.on('open', function(my_peer_id) {
      console.log('My peer ID is: ' + my_peer_id);
    });
    

    并将令牌发送给您想要的任何其他人(通过文本文件、网络聊天...等)

    然后其他连接它使用上面的令牌

    //the other one
    var conn = peer.connect(other_peer_id);
    

    房间主人检测到有人进入房间后。

    与信号服务器断开连接,令牌将无法使用

    //room owner side
    peer.disconnect()
    

    关于客户端生成和读取文件,我推荐你阅读下面的文章。

    1. http://www.html5rocks.com/en/tutorials/file/dndfiles/从文件中读取
    2. How to use filesaver.js另存为文件

    我相信 fileReader api 和 blob 的兼容性并不重要。 因为永远不会有支持webrtc但不支持fileReader api的浏览器

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-02
      • 2023-03-06
      • 2020-01-08
      • 1970-01-01
      • 2012-10-27
      • 2021-11-12
      • 2021-05-12
      • 2022-11-22
      相关资源
      最近更新 更多