Skip to content

用c#实现http服务器接受ajax请求,c#实现网页截图并上传文件到远程服务器 #36

Description

@abeet

目的

在ZCMS中专题可视化制作,原来的截图用的是html2canvas,其原理是解析html和css,在Canvas上绘制截图,相当于实现了浏览器的css解析部分的功能,不但无法正确还实际的界面效果,绘制的的速度还很慢,甚至会因为脚本错误导致无法返回截图。
现在的思路是用C#在本地跑一个http服务器,并响应js请求对网页截屏,然后上传图像到远程服务器。

实现过程

所以我们要开始一个新的项目,基于.NET Framework的实现

先看文档
https://docs.microsoft.com/zh-cn/dotnet/framework/index
记下可能要参考的文档
https://docs.microsoft.com/zh-cn/dotnet/framework/network-programming/network-programming-samples
《网络编程示例》
https://docs.microsoft.com/en-us/dotnet/api/system.net.httplistener?redirectedfrom=MSDN&view=netframework-4.7.2
没想到.NET Framework开启一个http访问也挺简单的。。。

遇到“c# 未能找到类型或命名空间”的解决
找到右侧的“解决方案“1个项目””下的子目录“引用”,右键点击,“添加引用”,选择“.net”,活动鼠标,找到“System.Drawing”,选中它,点击确定。就OK了!

在git上搜索
“Graphics.FromImage BackgroundImage WindowState ShowInTaskbar FormBorderStyle”
找到截图功能参考代码
https://github.com/Horiatu/PrintScreen/blob/master/PrintScreen/CaptureForm.cs
支持按下alt键

https://github.com/sysr-q/xcap/blob/master/src/Snap.cs
有图片上传示例

https://github.com/fish-li/ClownFish.Tucao/blob/master/src/client/ClownFish.Tucao.WinClient/CaptureForm.cs

https://github.com/Dinokaiz2/AUTONOTE/blob/master/AUTONOTE/SnipForm.cs
中文注释

https://github.com/adzm/BusinessCats/blob/master/SnippingCat.cs

https://github.com/rayel/SinaWeiboClient/blob/master/WeiboClient/Forms/ScreenShot.cs

在github上搜索”new HttpListener HttpListenerContext HttpListenerRequest 200 route“

”new HttpListener HttpListenerContext HttpListenerRequest 200 routes“
”new HttpListener HttpListenerContext HttpListenerRequest 200 router“
找了一些实现HTTPServer的代码,选择最简短的几个类

https://github.com/MemoryPenguin/CodeSync2/blob/master/CodeSync2-Server/Network/HttpServer.cs
https://github.com/klasbj/fsxrelay/blob/master/fsx_relay_console/HttpServer.cs
https://github.com/ktos/BasicRestServer/blob/master/BasicRestServer.Netmf/BasicRestServer.cs

结合
https://github.com/Dinokaiz2/AUTONOTE/blob/93e60d91b9/AUTONOTE/SnipForm.cs

https://github.com/ktos/BasicRestServer/blob/master/BasicRestServer.Netmf/BasicRestServer.cs
实现了,访问
http://localhost:8080/capture?x=11&y=22&w=444&h=333
将主屏幕的特定位置载图的效果。

现在要定位浏览器所在的窗口进行截图,我设想浏览器所在窗口即鼠标所在窗口,
于是在github上搜索
”AllScreens CopyFromScreen Cursor.Position“
找到如下代码,来获取当前鼠标所在屏幕的办法
https://github.com/pj-martins/ScreenCapture/blob/master/CaptureHelper.cs

将之前实现的word中图片上传到服务器的部分逻辑移到这个c#程序里

js交互部分比较简单,就不写了。

c#实现网页截图就这么完成了,代码量还挺少,发布后不到20k,耶。

还可以改进的地方,滚动窗口截长图——现在zcms里专题的编辑区是限定在一个iframe里的,要找到这个iframe并滚动它可能有点麻烦,容后再实现。

打包成服务后出现了一个大问题

总是截图失败,取到的鼠标位置总是0,0,取到的屏幕宽总是为1024*768,
在google上搜索“c# service Screen”
找到文章
https://stackoverflow.com/questions/4712532/why-does-print-screen-in-a-windows-service-return-a-black-image
原来出于安全考虑后台服务不允许读取屏幕。
只能把截屏程序另外写一个了。

查资料解决以下问题

  • C#怎么调用其他exe并传参
  • C#怎么设置windows程序不显示任务栏图标
  • C#被调用的程序怎么返回值或者怎么判断图片已写入
  • C# 强制退出程序的强健写法

所有问题解决后,仍然有问题还是获取不到真实屏幕,看来是另外一个问题了
搜索”服务 新进程 运行 Windows 7“——这个搜索词是在多次尝试后才得到的
发现文章
http://www.cnblogs.com/gnielee/archive/2010/04/08/session0-isolation-part2.html
再在github上搜索”CreateProcessAsUser“
找到项目
https://github.com/murrayju/CreateProcessAsUser
把代码搬过来,又有几个问题

  • 调试时执行 StartProcessAsCurrentUser 总是出错,
    查资料,并测试,后来发现,在以服务模式运行才能正常执行这个方法
  • StartProcessAsCurrentUser 传参数时,没有把第一个参数传过去,刚好我原来代码的第一个参数是图片保存路径,这导致了图片总是找不到,
    反复测试,用Logger输出参数,才发现参数少了一个,于是多加一个参数,终于跑通了

注意一下后台服务的 ApplicationData 目录在 C:\Users\abeet\AppData\Roaming\zving.com
而前台应用的 ApplicationData 目录在 C:\Windows\SysWOW64\config\systemprofile\AppData\Roaming

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions