65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 QR 码和 REST 架构在服务器屏幕上打开媒体文件的 HTTP Web 服务器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.29/5 (6投票s)

2012年1月27日

LGPL3

4分钟阅读

viewsIcon

44648

downloadIcon

550

一个命令行 Web 服务器,可以启动应用程序或在 HTTP 地址中打开作为参数提供的文件。可能可以使用 QR 码在屏幕上显示媒体。

引言

在头脑风暴会议中,出现了使用手机和 QR 码在屏幕上展示媒体的想法。需要以某种交互方式可视化我们项目的信息。将信息和 QR 码打印在传统纸张上,并配以交互式平板屏幕,结果可能会引起参观者的更多好奇。

应用程序的一个示例是连接到带有下面服务器应用程序的计算机的屏幕。在服务器上,放置四个不同的电影。在屏幕下方,放置四个与每个电影对应的 QR 码。然后,参观者可以使用他们的手机扫描 QR 码,并在屏幕上启动相应的电影。

要实现这一点,服务器端需要一个 HTTP Web 服务器,它侦听 HTTP 调用并在服务器本地打开文件或应用程序。然后,服务器连接到一个屏幕,在该屏幕上显示所选的应用程序/电影/图片/演示文稿。QR 码中可能存储的唯一信息是 URL 字符串。因此,HTTP 服务器必须能够使用 REST 架构打开 URL 字符串中提供的文件。

HTTP 还必须由活动的计算机用户启动。如果将其实现为服务,则无法在 Windows 中正常配置的屏幕连接上显示任何内容。

这种方法的主要优点是手机可以轻松读取 QR 码,而手机通常随身携带。在展览中,通常希望与系统进行交互,而额外的集成硬件成本很高。取而代之的是,您可以使用参观者的移动设备作为工具。您唯一需要做的就是购买一台便宜的计算机,并将其连接到一台漂亮的屏幕。然后,让您的参观者扫描 QR 码来回答问题、启动电影、启动演示文稿等。

允许打开的文件在代码中定义为一个文件夹。要打开文件夹中的文件,文件名为 HTTP REST 调用中提供的参数,例如:http://Myserver:8080/?file=openme.txt

使用代码

代码很简单,可以根据您希望显示文件的方式进行配置。对于电影和 PowerPoint,我发送参数以将媒体扩展到全屏。请参阅特定软件手册以了解如何与软件进行交互。

要创建用于启动应用程序的 QR 码,可以使用互联网上可用的任何 QR 码生成器,例如:http://qrcode.kaywa.com/。对于连接字符串,您需要服务器的地址或 IP、使用的端口以及要在服务器端显示的文件的名称或主页,即:http://your-address:your-port/?file=your-file

要启动服务器端应用程序,请以管理员模式启动 exe 文件(至少对我来说,这对于侦听端口是必需的)。默认端口是 8080,可以通过代码更改,或者通过提供端口作为参数来更改。例如,创建一个快捷方式并在快捷方式属性的命令字段中指定端口。

我增加了对流式传输视频到请求设备的支持。这是通过将参数 local=true 添加到 REST 调用来实现的,即:http://your-address:your-port/?file=your-file&local=true

代码

主循环基本上启动一个 HttpListener,并通过调用 StartProgram(带有 REST 参数中提供的文件)来响应所有调用,并以“Started”或在文件不存在或发生任何异常时的异常进行响应。

//Source for videos to play locally on the connected device
private static string httpfilesource = "http://desenergy.selfip.org/";
private static string filefolder = "C:\\Videos\\";

private static void Main(string[] args)
{
    var server = new HttpListener();
    int port;
    if (args != null && args.Length > 0 && int.TryParse(args[0], out port))
        server.Prefixes.Add(@"http://*:" + port + "/");
    else
        server.Prefixes.Add(@"<a href="http://*:8080/">http://*:8080/");
    while (true)
    {
        server.Start();
        HttpListenerContext context = server.GetContext();

        NameValueCollection query = context.Request.QueryString;
        bool local = false;
        string file = query["file"];
        //Play movies locally on the requesting device
        if (query["local"] != null)
            local = "true".ToLowerInvariant() == query["local"].ToLowerInvariant();
        string exc = "";
        string responseString = "";
        try
        {
            if (file != null)
            {
                //Local
                if (local)
                {
                    
                    responseString = "<HTML><BODY><video width=\"320\" height=\""
                                     + "240\" controls=\"controls\">"
                                     + "<source src=\"" + httpfilesource + file 
                                     + "\" type=\"video/ogg\" />"
                                     + "Your browser does not support the video tag."
                                     + "</video></BODY></HTML>";
                }
                else
                {
                    StartProgram(filefolder + file);
                    responseString = "<HTML><BODY> Startad </BODY></HTML>";
                }
            }
        }
        catch (Exception e)
        {
            exc = e.ToString();
        }

        HttpListenerResponse response = context.Response;
        // Construct a response.
        
        if (exc != "")
            responseString = "<HTML><BODY> Exception =" + 
                             exc + " </BODY></HTML>";
        byte[] buffer = Encoding.UTF8.GetBytes(responseString);
        response.ContentLength64 = buffer.Length;
        Stream output = response.OutputStream;
        output.Write(buffer, 0, buffer.Length);
        output.Close();
    }
}

下一步是实现 StartProgram 函数。

默认情况下,提供给 StartProgram 函数的文件由服务器执行。Windows 文件关联将负责如何执行文件。但是,在此实现中,我需要一些文件以全屏模式启动,例如,从一开始就以全屏模式启动电影、PowerPoint、Word 文件和主页。

为了实现全屏,应用程序将启动参数发送给实际的应用程序本身。发送的参数取决于所使用的应用程序,但实际文档或媒体始终作为参数之一提供。

特定程序的默认程序在常量字符串中定义。请注意,打开特定程序的字符串因安装而异。如果您想要更严格的设计,可以访问注册表来获取文件文件夹。

该方法基本上首先清理文件名中的一些北欧字母问题,然后分析字符串并以正确的应用程序启动它。如果文件类型没有默认应用程序,则应用程序会尝试自行启动文件。

//Define Your Paths
private const String Reader = @"C:\Program Files (x86)\Adobe\Acrobat 10.0\Acrobat\Acrobat.exe";
private const String Explorer = @"C:\Program Files (x86)\Internet Explorer\iexplore.exe";
private const String PowerPoint = @"C:\Program Files (x86)\Microsoft Office\Office14\POWERPNT.EXE";
private const String WinWord = @"C:\Program Files (x86)\Microsoft Office\Office14\winword.exe";
private const String WMPlayer = @"C:\Program Files\Windows Media Player\wmplayer.exe";


private static void StartProgram(string s)
{
    string file = String.Copy(s);
    if (file != null)
    {
        file = file .Replace("ö", "ö");
        file = file.Replace("ä", "ä");
        file = file.Replace("Ã¥", "å");
    }

    string t;
    try
    {
        t = file.Remove(0, file.LastIndexOf(".", StringComparison.Ordinal));
    }
    catch
    {
        t = s;
    }

    if (file.StartsWith("http://"))
    {
        StartProcess(Explorer,
                     "-k " + "\"" + file + "\"");
    }
    else
    {
        switch (t.ToLowerInvariant())
        {
            case ".ppt":
            case ".pptx":
                StartProcess(PowerPoint,
                             "/S " + "\"" + file + "\"");
                break;
            case ".doc":
            case ".docx":
                StartProcess(WinWord,
                             "/fullscreen " + "\"" + file + "\"");
                break;
            case ".mpg":
            case ".mpeg":
            case ".mp4":
            case ".avi":
            case ".ogg":
                StartProcess(WMPlayer,
                             "\"" + file + "\"" + " /fullscreen");
                break;
            case ".pdf":
                StartProcess(Reader,
                             "\"" + file + "\"");
                break;
            default:
                StartProcess(file, null);
                break;
        }
    }
}

最后一部分关闭前一个进程并启动新进程。前一个进程存储在一个静态字段中,因此可以在启动下一个进程之前关闭。

private static Process _process;

private static void StartProcess(string program, string argumentfile)
    try
    {
        if (_process != null)
            _process.CloseMainWindow();
    }
    catch (Exception)
    {
    }
    _process = new Process
                   {
                       StartInfo =
                           {
                               FileName = program,
                               Arguments = argumentfile,
                               WindowStyle = ProcessWindowStyle.Maximized
                           }
                   };
    // Configure the process using the StartInfo properties. 
    _process.Start();
}

关注点

如果您不想将计算机暴露给外部世界,您可以设置一个开放的无线网络,这是连接到服务器的唯一方式。

© . All rights reserved.