最近一段时间有用markdown做笔记,其他都好,但是markdown插入图片挺麻烦的,特别是想截图之后直接插入的时候。需要首先把图片保存了,然后还要上传到一个地方生成链接才能插入。如果有个工具可以直接上传图片或者截图生成markdown可以用的链接就好了。所以决定自己下班后写一个,不过自己挺菜的,也就能用,代码完全是渣不能看。。。在这里把自己的思路还有其中遇到的问题记录一下。

  首先需要选一个图床,我选了七牛,主要是一个是有免费的空间,加上提供了SDK,这样就能写程序上传了。语言挑了C#,因为感觉WPF写界面还算方便吧。根据七牛文档写得,首先要用nuget下载官方的SDK,这个可以参考http://developer.qiniu.com/code/v6/sdk/csharp.html

  所要完成的功能:能够选择图片上传,能够自动上传截图,生成markdown可用的链接

1、界面

主界面:

  

设置账号界面:

2. 选择图片上传功能

点击中间区域弹出文件浏览框,选择图片后上传。这个通过绑定控件的鼠标事件来完成,上传图片用到了七牛提供的API。主体函数如下,首先是通过比对文件的hash值来判断是否本地以及远程已经有过上传,如果没有上传过,就通过七牛提供的上传API进行上传,并在预览区显示图片。

  1. private bool UpLoadFile(string filepath)
  2. {
  3. string filename = System.IO.Path.GetFileName(filepath);
  4. Qiniu.Util.Mac lMac = new Qiniu.Util.Mac(UserAccount.AccessKey, UserAccount.SecretKey);
  5. string lRemoteHash = RemoteFileInfo.RemoteFileStat(lMac, UserAccount.SpaceName, filename);
  6. bool lSkip = false;
  7. bool lUpLoadSuccess = false;
  8. //check local
  9. string lLocalHash = String.Empty;
  10. if (!string.IsNullOrEmpty(lRemoteHash))
  11. {
  12. lLocalHash = QETag.hash(filepath);
  13.  
  14. if (historyLog.ContainsKey(lLocalHash))
  15. {
  16. if(historyLog[lLocalHash].Contains(filename))
  17. {
  18. lSkip = true;
  19. URL = CreateURL(filename);
  20. lUpLoadSuccess = true;
  21. }
  22. }
  23. else if (string.Equals(lLocalHash, lRemoteHash))
  24. {
  25. lSkip = true;
  26. URL = CreateURL(filename);
  27. lUpLoadSuccess = true;
  28. }
  29. }
  30. if (!lSkip)
  31. {
  32. putPolicy.Scope = UserAccount.SpaceName;
  33. putPolicy.SetExpires( * * );
  34. string lUploadToken = Auth.createUploadToken(putPolicy, lMac);
  35. UploadManager lUploadMgr = new UploadManager();
  36. lUploadMgr.uploadFile(filepath, filename, lUploadToken, null, new UpCompletionHandler(delegate (string key, ResponseInfo responseinfo, string response)
  37. {
  38. if (responseinfo.StatusCode != )
  39. {
  40. MessageStr = Properties.Resources.ErrorMessage;
  41. }
  42. else
  43. {
  44. MessageStr = Properties.Resources.SuccessMessage;
  45. if (historyLog.ContainsKey(lLocalHash))
  46. {
  47. historyLog[lLocalHash].Add(filename);
  48. }
  49. URL = CreateURL(filename);
  50. lUpLoadSuccess = true;
  51. }
  52. }));
  53. }
  54.  
  55. if (lUpLoadSuccess)
  56. {
  57. DisplayImage(filepath);
  58. MessageStr = URL;
  59. }
  60.  
  61. return lUpLoadSuccess;
  62. }

3. 截图上传

为了完成这个,搜了下资料,需要用到win32的两个函数,分别是AddClipboardFormatListener以及RemoveClipboardFormatListener,然后检查系统消息是否是WM_CLIPBOARDUPDATE。为了给用户提供选择是否开启这个,在主界面上添加了一个button来控制是否开启。因为七牛SDK的上传api的参数是一个文件路径,所以这里我首先会将截图存储到本地再上传。

  1. private void CBViewerButton_Click(object sender, RoutedEventArgs e)
  2. {
  3. if(!IsViewing)
  4. {
  5. InitCBViewer();
  6. this.CBViewerButton.Content = "停止监控";
  7. }
  8. else
  9. {
  10. StopCBViewer();
  11. this.CBViewerButton.Content = "监控剪切板";
  12. }
  13. }
  14. private void InitCBViewer()
  15. {
  16. WindowInteropHelper lwindowih = new WindowInteropHelper(this);
  17. hWndSource = HwndSource.FromHwnd(lwindowih.Handle);
  18.  
  19. hWndSource.AddHook(this.WndProc);
  20. Win32.AddClipboardFormatListener(hWndSource.Handle);
  21. IsViewing = true;
  22. }
  23.  
  24. private void StopCBViewer()
  25. {
  26. Win32.RemoveClipboardFormatListener(hWndSource.Handle);
  27. hWndSource.RemoveHook(this.WndProc);
  28. IsViewing = false;
  29. }
  30.  
  31. private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParm, ref bool handled)
  32. {
  33. if(msg == Win32.WM_CLIPBOARDUPDATE)
  34. {
  35. ProcessClipBoard();
  36. }
  37. return IntPtr.Zero;
  38. }
  39.  
  40. private void ProcessClipBoard()
  41. {
  42. if(System.Windows.Clipboard.ContainsImage())
  43. {
  44. MessageStr = Properties.Resources.UpLoading;
  45.  
  46. BmpBitmapEncoder enc = new BmpBitmapEncoder();
  47. enc.Frames.Add(BitmapFrame.Create(System.Windows.Clipboard.GetImage()));
  48.  
  49. string lFileName = CreateFileName();
  50. string lSaveFilePath = System.IO.Path.Combine(Properties.Resources.ImageSavePathDir, lFileName);
  51. using (FileStream fs = new FileStream(lSaveFilePath, FileMode.OpenOrCreate, FileAccess.Write))
  52. {
  53. enc.Save(fs);
  54. fs.Close();
  55. }
  56.  
  57. //because unkown reason, when use wechat snapshot hotkey, the message will process twice, to avoid this, check whether we save the same file
  58. string lLocalHash = QETag.hash(lSaveFilePath);
  59. if(historyLog.ContainsKey(lLocalHash))
  60. {
  61. File.Delete(lSaveFilePath);
  62. URL = CreateURL(historyLog[lLocalHash][]);
  63. lSaveFilePath = System.IO.Path.Combine(Properties.Resources.ImageSavePathDir, historyLog[lLocalHash][]);
  64. }
  65. else
  66. {
  67. if(!UpLoadFile(lSaveFilePath))
  68. {
  69. File.Delete(lSaveFilePath);
  70. }
  71. }
  72. }
  73. }

PS:在做这个的时候我碰到一个问题就是当我用微信的截图快捷键的时候,这个Clipboard事件会被触发两次,为了解决这个,我的做法是判断本地的上传记录,比对文件的hash值。如果已经上传过,就把后来又存储的文件给删除掉。目前我也想不到其他方式,暂且这样处理吧。

4. 账号设置

用七牛做图床需要设置四个参数,分别是目标空间名,Accesskey, secrectkey以及域名。为了方便存储和读取,用了C#里的xml序列化和反序列化

  1. if (File.Exists(Properties.Resources.ConfigFilePath))
  2. {
  3. XmlSerializer xs = new XmlSerializer(typeof(AccountInfo));
  4. using (Stream s = File.OpenRead(Properties.Resources.ConfigFilePath))
  5. {
  6. UserAccount = (AccountInfo)(xs.Deserialize(s));
  7. }
  8. }
  1. using (Stream s = File.OpenWrite(Properties.Resources.ConfigFilePath))
  2. {
  3. XmlSerializer xs = new XmlSerializer(typeof(AccountInfo));
  4. xs.Serialize(s, MainWindow.UserAccount);
  5. }

5. 未完成功能:历史记录查看等

完整代码:

https://github.com/HaoLiuHust/QiniuUpload

PS: 代码很烂,还需要多练

QiniuUpload- 一个方便用七牛做图床然后插入markdown的小工具的更多相关文章

  1. win10 uwp 使用 asp dotnet core 做图床服务器客户端

    原文 win10 uwp 使用 asp dotnet core 做图床服务器客户端 本文告诉大家如何在 UWP 做客户端和 asp dotnet core 做服务器端来做一个图床工具   服务器端 从 ...

  2. 分享一个超级好用的SM图床

    分享一个超级好用的SM图床 ​ 大家都知道我是一个喜欢sm Markdown的人,但是Markdown有个很不方便的地方,就是图片的插入,一般用Markdown编辑器(我用的是Typora)直接插入图 ...

  3. 图床plus演示 | 图床及在线分享演示文稿工具

    文章目录 关于图床 什么是图床? 墙内 墙外 关于在线分享演示文稿 在线分享演示文稿 工具分享 待补充 关于图床 什么是图床? 这并不是一个多么高大上的名词概念!用比较通俗的话来说,当你在撰写新文章时 ...

  4. u-tools图床便捷生成markdown图片

    u-tools 图床 上传图片生成markdown图片非常便捷. 支持的图片服务器有几种,其中搜狗.网易和掘金的加载速度更快些: 也可以用阿里与和腾讯云的OSS; 其中网易生成图片不是原图尺寸好像被改 ...

  5. 使用GitHub API上传文件及GitHub做图床

    本文介绍GitHub API基础及上传文件到仓库API,并应用API将GitHub作为图床 GitHub API官方页面 GitHub API版本 当前版本为v3,官方推荐在请求头中显示添加版本标识. ...

  6. Typora使用教程 之 PicGo集成做图床

    目录 一.Typora是什么 二.研究它的原因 三.需要解决的问题 四.解决图床问题 1.下载PicGo 2.安装下载的PicGo,并根据下图所示配置(必须安装nodejs,否则插件一直是" ...

  7. 自己做的加速app测试流程的小工具,目前打算开放使用,想注册的朋友抓紧了,嘻嘻

    为了加速小团队app的测试流程做了这个东西,www.xunce.net 主要特性: web: 一键上传app,方便随时下载 备注测试要点 添加附件,如checklist等文档  自动识别app版本,名 ...

  8. 在这个插件帮助下,终于用上免费的Https协议外链的图床了

    前天,强哥发了一篇推文,讲述了应该如何免费且快速的生成自己的博客网站: 期间也有提到一点就是我们在写博客的时候,因为使用的是Markdown格式的文件,而如果想要​Markdown格式的文件在图片上传 ...

  9. Markdown编辑器及图床推荐

    Typora和自动图床工具 Typora 地址 ,极致简洁,界面很漂亮,最重要的是所见即所得 百度云搬运 密码:xi01 自动图床工具 需要七牛云做图床,感谢作者,详见博客 使用方法,只需两步即可完成 ...

随机推荐

  1. C#Transfrom

    代码如下: private void btnConvertType_Click(object sender, EventArgs e) { if (rdo_btn_ConvertObject.Chec ...

  2. 用MVC4练习,后台用aspx,数据库DemoDb《MvcUserDemo》

    将ado.net的cs文件SqlHelper.cs放入解决方案 using System; using System.Collections.Generic; using System.Linq; u ...

  3. SQL从入门到基础–08 Union、Union all及案例

    一.联合结果集 1. 简单的结果集联合: Select FNumber,FName,FAge from T_Employee union select FidCardNumber,FName,FAge ...

  4. MySQL主从问题

    Mysql数据库主从心得整理      管理mysql主从有2年多了,管理过200多组mysql主从,几乎涉及到各个版本的主从,本博文属于总结性的,有一部分是摘自网络,大部分是根据自己管理的心得和经验 ...

  5. memcached学习笔记——连接模型

    文章链接:http://www.hcoding.com/?p=121 个人站点:JC&hcoding.com memcached是什么呢?memcached是一个优秀的.高性能的内存缓存工具. ...

  6. [算法]分治算法(Divide and Conquer)

    转载请注明:http://www.cnblogs.com/StartoverX/p/4575744.html 分治算法 在计算机科学中,分治法是建基于多项分支递归的一种很重要的算法范式.字面上的解释是 ...

  7. Factorial Solved Problem code: FCTRL

    import sys #import psyco #很奇怪,这题用psyco就runtime error #psyco.full() def z(n): #这个应该是技巧的一种算法 r = 0 whi ...

  8. QT下实现对Linux Shell调用的几种方法

    使用QProcess QThread ============================================ #include <QProcess>int main(){ ...

  9. Qt的Script、Quick、QML的关系与总结

    背景 最近在学QML,感觉也不难,就是一直以来接触 Qt 的脚本类的东西的顺序是Script.Quick1.Declarative.Quick2.QML.那么每一个都是干什么的呢,这些东西搞的我有点混 ...

  10. POJ 3280 Cheapest Palindrome 简单DP

    观察题目我们可以知道,实际上对于一个字母,你在串中删除或者添加本质上一样的,因为既然你添加是为了让其对称,说明有一个孤立的字母没有配对的,也就可以删掉,也能满足对称. 故两种操作看成一种,只需要保留花 ...