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

在线电子表格,一个低延迟的 HTML5 WebSocket 云服务(SaaS),采用 C# .NET(类似 Google Sheets)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.90/5 (41投票s)

2015年3月31日

CPOL

12分钟阅读

viewsIcon

104098

downloadIcon

2867

构建您自己的云电子表格(类似 Microsoft Excel、Google Sheets),通过 Web 浏览器暴露电子表格工作簿。用户可以使用 Web 浏览器创建类似 Excel 的电子表格,保存、共享、输入公式计算表格中的数据等。

下载次数

来自 Wiki

参考 (1)
“Google Docs、Sheets、Slides 和 Forms 分别是 Google 通过其 Google Drive 服务提供的免费、基于网络的文字处理器、电子表格程序、演示程序和调查程序。该套件允许用户在线创建和编辑文档,同时与其他用户实时协作。”

参考 (2)
“软件即服务(SaaS)是一种软件许可和交付模式,其中软件以订阅为基础进行许可,并集中托管。”

根据 Gartner Group 的估计,SaaS 销售额在 2010 年达到 100 亿美元,并预计在 2011 年增至 121 亿美元,比 2010 年增长 20.7%。  Gartner Group 估计,到 2015 年,SaaS 收入将比 2010 年翻一番多,达到预测的 213 亿美元。

引言

我们中的许多人可能多年来一直使用 Microsoft Excel 电子表格来满足工作和个人需求。  过去几年,这些工作表已在线提供为云服务,这一点我们大多数人都知道。  Google Sheets 是众多云计算文档共享服务之一。  您是否想为您的客户或出于兴趣创建一个在线云电子表格服务(SaaS)?  继续阅读……

图 1: 在 Microsoft Internet Explorer 中打开的电子表格。  请注意,当更改相关单元格的值时,计算过的(公式)单元格会进行计算。

您想如何进行?

  • 如果您想查看此 SaaS,请转到“快速演示”部分。  您可以在几秒钟内进行设置并立即查看。
  • 如果您想了解它是如何工作的,请继续阅读。

快速演示

  • 通过单击页面顶部的链接,将演示二进制文件复制到您的计算机。
  • 运行 saasSpreadSheet.exe。  如果出现防火墙警告,请单击“允许”按钮以启动服务。
  • 打开 spreadSheet.html。

图 2: 电子表格页面未连接。  注意右上方闪烁的红灯。  使用的浏览器:Google Chrome。

  • 我已经为您准备了一个示例工作表!  因此,在编辑框中输入“test”,如下图所示。  然后,单击“打开”按钮。  如果服务已启动并正在运行,您将看到电子表格已加载,如下图所示。  修改数量、价格或多头/空头列。  您将看到“头寸”列会根据公式自动计算。  您知道,您可以保存和检索文档。

如果您想从头开始,请输入一个新的名称。  然后,单击“打开”。  您将获得一个全新的工作表开始。  输入新数据和数学公式进行尝试。

图 3: 电子表格已在 Google Chrome 中打开并连接。  注意右上方绿色的连接灯。

  • 停止服务。  即,关闭您在步骤 2 中启动的可执行文件。  您将看到状态更改为“未连接”。

图 4: 随着服务的停止,电子表格的闪烁红灯再次亮起,表示现在已离线。  使用的浏览器:Google Chrome。

为什么选择云服务

如果您已经了解了云计算的优势,可以跳过此部分。  如果不了解,这里简要介绍一下云平台的优势。
最近,我发送了一封带有文件附件的电子邮件。  不幸的是,第二天早上,他们确认他们*没有*收到。  猜猜怎么着,文件大小超限了,太大了。  工作延迟——时间就是金钱。  嗯,我本可以用云服务发送那个该死的文件。  我们都会经历这种经历。  这开始了云服务的优势。

  • 成本效益:传统的桌面/企业软件在许可、支持、硬件升级等方面成本很高。  而基于云的软件主要在您的浏览器上按需付费工作。
  • 备份和恢复:您几乎不必担心备份、工作恢复。  云服务应该将其存储在不同的位置。
  • 轻松访问信息:如我所述,发送带有简单软链接的电子邮件比通过电子邮件实际传输整个文件要好得多。  这使得共享更加容易。
  • 技术基础设施:公司可以只关注核心业务,而无需建立不必要且昂贵的信息技术基础设施来支持其业务。
  • 秒级全球化:以最少的基础设施轻松地将您的业务应用程序部署到全球。

尽管如此,云计算还有许多更详尽的优势。  这就是为什么这项技术正在迅速扩展。

设计权衡

开发传统应用程序和 SaaS(软件即服务)Web 应用程序之间存在差异。  传统应用程序从用户的硬盘加载到 RAM。  而 SaaS 则在服务器端进行大部分繁重的工作。  一个瘦客户端,通常是 Web 浏览器,仅显示应用程序的 GUI 部分。

  • 与用户建立**安全(SSL/TLS)**连接很重要。  这是一个额外的步骤。  有时,这意味着您需要从有效的 CA 获取安全密钥,可能需要静态 IP,可能需要经过额外的验证流程。  但非常值得。  比较权衡——您的用户安全隐私与不必要的窃听。
  •  **安全开发:**  许多 CEO 认为,通过获取 SSL/TLS 即可购买安全,问题解决。  但黑客也可以通过安全通道访问您的系统资源。  黑客可以采用缓冲区溢出、SQL 注入等技术。  这里的权衡是安全开发与功能开发投入多少时间和金钱。
  • **硬件冗余与软件冗余:**  如您所知,云应用程序的主要原因是其可靠性。  云服务需要拥有用户文件的多个/多站点备份,以应对灾难。  冗余可以通过硬件或软件实现。  例如,考虑投资硬件 RAID 控制器以安装基于 ZFS 的软件冗余。  这种权衡非常微妙,因为我们在这两方面都有利弊。
  • **无限一切:**  当您提供无限的东西时要小心。  今天,我们已经习惯了无限存储、无限免费 Web 应用等营销手段。  这在短期内可以抓住市场。  但从设计角度来看,任何无限的东西都不是长期可持续的。  这就是为什么许多精明的企业正在转向为个人用户提供无限免费服务,但对企业用户收费。  假设您为用户提供电子表格云服务。  无限单元格、无限存储和无限的一切。  一个别有用心的用户可以通过某种自动化程序填充单元格来使您的服务器瘫痪。  这将影响您那些真正使用该服务的良好用户。  这迫使您对用户施加一定的限制,例如,每天 10 个工作表,每天 50 MB 等。  因此,这里的权衡是您希望对用户施加多大限制。

简要说明

本文介绍如何构建自己的核心云服务。  因此,构建自己的云服务是一项艰巨的任务。  它需要专业的企业级服务器硬件/软件。  这些是标准项目,可以从外部供应商处构建或购买——这是资本投资。  然而,云服务中的关键部分是通过万维网(互联网)向客户公开的核心服务。  例如,Google Sheets 公开可以轻松创建、编辑、保存和共享的电子表格。  这种核心服务是本文的范围。  在本文中,我们将使用 C# .NET 创建一个服务,以公开电子表格功能,并能够打开、编辑、计算数学公式、保存和共享电子表格工作簿。  即,软件即服务(SaaS)的电子表格工作簿。

图 5: 云 SaaS 服务

详细说明

让我们从定义一些需求开始。  我们想构建一个提供电子表格工作簿的服务。  为简洁起见,我们支持一些基本功能。

  • 用户应打开工作簿并获得类似工作簿的屏幕。
  • 用户应创建新工作簿、编辑并保存它。
  • 用户应使用工作簿执行数学计算。

HTML5 WebSocket 是万维网历史上的一项重大变革。  它能够在 Web 浏览器和您的服务之间实现低延迟、全双工、持久的通信。  您可以在这里阅读更多关于它的信息(参考 3)。  现在,关键问题:Web 浏览器和服务器之间的低延迟 TCP 通信得到了解决。  如果您需要有关此工作原理的更多详细信息,请参阅 参考 (3) 链接。  本项目使用了来自 参考 (3) 链接的 HTML5 WebSocket 流。

此电子表格 SaaS 的服务器端代码出奇地简单。  我们先看看主函数。  主函数是 C# 中服务器应用程序的入口点。

      static void Main(string[] args)
        {
            html5Stream stream = new html5Stream();     // Line 1
            stream.startServer();            // Line 2
        }

主函数的第一行创建一个 html5Stream 对象。  第二行启动服务。  第二行是一个阻塞调用。  因此,服务器将一直运行,直到该调用返回。

让我们看看 startServer 方法中的关键部分。  这个方法所做的就是接受来自客户端的新连接。  在我们的例子中,客户端是 Web 浏览器。  Socket 上的 Accept 调用将在客户端尝试新连接时返回。  新连接建立后,调用处理将被定向到 OnAcceptConnection 方法。  然后,它会循环回到等待另一个新客户端。  此函数就像办公室接待员一样。  当新访客进入工作场所时,接待员会将访客处理转给适当的人员,然后回去处理新的电话/访客。

   public void startServer(string endPt = "", bool demo = false)
    {
    --------
    --------
      while (!Console.KeyAvailable)
      {
        Socket ws = serverSocket.Accept();
        ThreadPool.QueueUserWorkItem(new WaitCallback(OnAcceptConnection), ws);

        counter++;
      }

          -------
    -------
    }


OnAcceptConnection 为已连接的客户端创建唯一 ID。  以后,将使用此唯一 ID 来识别客户端。  使用唯一 ID 标识客户端有助于我们提供适当的响应。  毕竟,每个客户端都将处理自己的电子表格工作簿。  我们需要向每个人发送正确的工作簿数据。  此方法检查是否已保存文件并且可以打开。  如果文件数据可用,则将文件内容流式传输到客户端。  否则,此方法将流式传输通用的 initData。  initData 包含一个空的电子表格工作簿。

    private void OnAcceptConnection(object param)
    {
 
        ------------
        ------------
          int rcvBytes = client.Receive(buffer);
    
        ----------
          clientResp = File.ReadAllText(clientInitialData[1]);
          if (clientResp.Length <= 0)
          {
              clientResp = initData;
          }

        -----------
            uniqueId = getUniqueId();
        -----------
            clientList.Add(uniqueId, clientData);

        -----------
            setStreamData(uniqueId, clientResp);
    }

此时,客户端 Web 浏览器会看到一个空的电子表格工作簿。  用户可以使用此工作表输入数据、计算数学公式。  每当用户完成一个单元格的输入并移至下一个单元格时,就会向服务器发出更新调用。  服务器端计算所需的公式(如果存在),然后将工作表发送回客户端。  用户看不到页面刷新。  所有这些都发生在后台。  用户可以看到工作表在键入时即时更新新计算。  当用户完成工作时,可以通过单击保存按钮来保存此工作表。  保存请求时,将作为第一个字节数据发送一个特殊的“s”。  在服务器端,这会执行保存操作。  在专业版本中,此保存操作需要发生在高性能数据库上。  在这里,我们为了简洁起见将数据保存在文件中。  这是执行此操作的服务器端代码。

    private void checkSaveOrOpen(long uniqueId, ref string data)
    {
        string[] dataRcvd = data.Split(new char[] {','}, 3);
        if (string.Compare(dataRcvd[0], "s") == 0)
        {
            try
            {
                data = 'u' + data.Remove(0, 1);
                File.WriteAllText(dataRcvd[1], data);
            }
            catch (Exception ex)
            {
                System.Console.WriteLine("Error: Save failed for clientId: {0}, {1}", uniqueId, ex.Message);
            }
        }
        ----------
    ----------

    }

上面的代码检查接收到的数据第一个字节是否包含字母“s”。  如果是,则翻转该字节并将数据保存到文件中。  它将字节翻转为“u”以确保保存完成。  这有助于避免为每个客户端请求重复保存。  最后,电子表格的计算由 muParser 完成。  这是一个快速的数学表达式解析器。  请阅读参考 (3) 中的文章,其中使用了此解析器库。

这就完成了此电子表格提供的功能的一个完整的回合。

关注点

  • 可以向此项目添加专业的电子表格的所有功能。  为简单起见,此在线电子表格提供基本功能,例如创建新工作表、打开现有工作表、保存工作表和数学公式计算。  本文/项目的目标是解释如何构建一个基本的可行原型。  专业工作表需要付出努力。  如果您需要专业的,请联系我。
  • 有一个小功能可以显示电子表格是在线还是离线。  如果工作表离线,顶部会闪烁一个小红灯。  绿灯表示工作表在线。  这个小功能仅通过两行代码实现。  客户端的这两个方法以及一个 gif 文件提供了这个漂亮的小有用功能。
function statusDisconnect()
{
        statusLED.src = "redlight.gif"
        statusTxt.innerHTML  = "Not Connected";
}

function statusConnected()
{
        statusLED.src = "greenlight.gif"
        statusTxt.innerHTML  = "Connected";
}
  • 在客户端,处理键盘输入,如退格键、箭头键、常规键等,需要额外的代码。  为简单起见和无缝工作,我使用了一个 HTML 输入框作为我们的输入。  用户在 HTML 输入框中键入的任何内容都会传输到电子表格单元格。  这样,就避免了客户端处理键盘的代码。

  • 如果您注意到计算列未按预期工作,请检查您的服务工作目录中是否包含 muParser.dll。

我诚挚感谢..

感谢您阅读本文。  我很乐意收到您的反馈。  如果您喜欢这篇文章,请在页面顶部投票支持,并留下您的评论。

非常感谢 muParser,这是此网格中使用的数学解析库(参考 4)。  这是一个相当快的表达式解析库。  感谢 https://cacoo.com。  我使用他们的在线工具为本文创建图表。

参考文献

1. 软件即服务
2. Google Docs
3. HTML WebSocket 流
4. 数学表达式解析器

历史

  • 2015 年 3 月 31 日 - 第一个版本
  • 2015 年 4 月 1 日 - 添加了“设计权衡”部分。
  • 2015 年 4 月 7 日 - 移动了“设计权衡”部分。
© . All rights reserved.