QiniuUpload- 一个方便用七牛做图床然后插入markdown的小工具
最近一段时间有用markdown做笔记,其他都好,但是markdown插入图片挺麻烦的,特别是想截图之后直接插入的时候。需要首先把图片保存了,然后还要上传到一个地方生成链接才能插入。如果有个工具可以直接上传图片或者截图生成markdown可以用的链接就好了。所以决定自己下班后写一个,不过自己挺菜的,也就能用,代码完全是渣不能看。。。在这里把自己的思路还有其中遇到的问题记录一下。
首先需要选一个图床,我选了七牛,主要是一个是有免费的空间,加上提供了SDK,这样就能写程序上传了。语言挑了C#,因为感觉WPF写界面还算方便吧。根据七牛文档写得,首先要用nuget下载官方的SDK,这个可以参考http://developer.qiniu.com/code/v6/sdk/csharp.html。
所要完成的功能:能够选择图片上传,能够自动上传截图,生成markdown可用的链接
1、界面
主界面:
设置账号界面:
2. 选择图片上传功能
点击中间区域弹出文件浏览框,选择图片后上传。这个通过绑定控件的鼠标事件来完成,上传图片用到了七牛提供的API。主体函数如下,首先是通过比对文件的hash值来判断是否本地以及远程已经有过上传,如果没有上传过,就通过七牛提供的上传API进行上传,并在预览区显示图片。
private bool UpLoadFile(string filepath)
{
string filename = System.IO.Path.GetFileName(filepath);
Qiniu.Util.Mac lMac = new Qiniu.Util.Mac(UserAccount.AccessKey, UserAccount.SecretKey);
string lRemoteHash = RemoteFileInfo.RemoteFileStat(lMac, UserAccount.SpaceName, filename);
bool lSkip = false;
bool lUpLoadSuccess = false;
//check local
string lLocalHash = String.Empty;
if (!string.IsNullOrEmpty(lRemoteHash))
{
lLocalHash = QETag.hash(filepath); if (historyLog.ContainsKey(lLocalHash))
{
if(historyLog[lLocalHash].Contains(filename))
{
lSkip = true;
URL = CreateURL(filename);
lUpLoadSuccess = true;
}
}
else if (string.Equals(lLocalHash, lRemoteHash))
{
lSkip = true;
URL = CreateURL(filename);
lUpLoadSuccess = true;
}
}
if (!lSkip)
{
putPolicy.Scope = UserAccount.SpaceName;
putPolicy.SetExpires( * * );
string lUploadToken = Auth.createUploadToken(putPolicy, lMac);
UploadManager lUploadMgr = new UploadManager();
lUploadMgr.uploadFile(filepath, filename, lUploadToken, null, new UpCompletionHandler(delegate (string key, ResponseInfo responseinfo, string response)
{
if (responseinfo.StatusCode != )
{
MessageStr = Properties.Resources.ErrorMessage;
}
else
{
MessageStr = Properties.Resources.SuccessMessage;
if (historyLog.ContainsKey(lLocalHash))
{
historyLog[lLocalHash].Add(filename);
}
URL = CreateURL(filename);
lUpLoadSuccess = true;
}
}));
} if (lUpLoadSuccess)
{
DisplayImage(filepath);
MessageStr = URL;
} return lUpLoadSuccess;
}
3. 截图上传
为了完成这个,搜了下资料,需要用到win32的两个函数,分别是AddClipboardFormatListener以及RemoveClipboardFormatListener,然后检查系统消息是否是WM_CLIPBOARDUPDATE。为了给用户提供选择是否开启这个,在主界面上添加了一个button来控制是否开启。因为七牛SDK的上传api的参数是一个文件路径,所以这里我首先会将截图存储到本地再上传。
private void CBViewerButton_Click(object sender, RoutedEventArgs e)
{
if(!IsViewing)
{
InitCBViewer();
this.CBViewerButton.Content = "停止监控";
}
else
{
StopCBViewer();
this.CBViewerButton.Content = "监控剪切板";
}
}
private void InitCBViewer()
{
WindowInteropHelper lwindowih = new WindowInteropHelper(this);
hWndSource = HwndSource.FromHwnd(lwindowih.Handle); hWndSource.AddHook(this.WndProc);
Win32.AddClipboardFormatListener(hWndSource.Handle);
IsViewing = true;
} private void StopCBViewer()
{
Win32.RemoveClipboardFormatListener(hWndSource.Handle);
hWndSource.RemoveHook(this.WndProc);
IsViewing = false;
} private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParm, ref bool handled)
{
if(msg == Win32.WM_CLIPBOARDUPDATE)
{
ProcessClipBoard();
}
return IntPtr.Zero;
} private void ProcessClipBoard()
{
if(System.Windows.Clipboard.ContainsImage())
{
MessageStr = Properties.Resources.UpLoading; BmpBitmapEncoder enc = new BmpBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(System.Windows.Clipboard.GetImage())); string lFileName = CreateFileName();
string lSaveFilePath = System.IO.Path.Combine(Properties.Resources.ImageSavePathDir, lFileName);
using (FileStream fs = new FileStream(lSaveFilePath, FileMode.OpenOrCreate, FileAccess.Write))
{
enc.Save(fs);
fs.Close();
} //because unkown reason, when use wechat snapshot hotkey, the message will process twice, to avoid this, check whether we save the same file
string lLocalHash = QETag.hash(lSaveFilePath);
if(historyLog.ContainsKey(lLocalHash))
{
File.Delete(lSaveFilePath);
URL = CreateURL(historyLog[lLocalHash][]);
lSaveFilePath = System.IO.Path.Combine(Properties.Resources.ImageSavePathDir, historyLog[lLocalHash][]);
}
else
{
if(!UpLoadFile(lSaveFilePath))
{
File.Delete(lSaveFilePath);
}
}
}
}
PS:在做这个的时候我碰到一个问题就是当我用微信的截图快捷键的时候,这个Clipboard事件会被触发两次,为了解决这个,我的做法是判断本地的上传记录,比对文件的hash值。如果已经上传过,就把后来又存储的文件给删除掉。目前我也想不到其他方式,暂且这样处理吧。
4. 账号设置
用七牛做图床需要设置四个参数,分别是目标空间名,Accesskey, secrectkey以及域名。为了方便存储和读取,用了C#里的xml序列化和反序列化
if (File.Exists(Properties.Resources.ConfigFilePath))
{
XmlSerializer xs = new XmlSerializer(typeof(AccountInfo));
using (Stream s = File.OpenRead(Properties.Resources.ConfigFilePath))
{
UserAccount = (AccountInfo)(xs.Deserialize(s));
}
}
using (Stream s = File.OpenWrite(Properties.Resources.ConfigFilePath))
{
XmlSerializer xs = new XmlSerializer(typeof(AccountInfo));
xs.Serialize(s, MainWindow.UserAccount);
}
5. 未完成功能:历史记录查看等
完整代码:
https://github.com/HaoLiuHust/QiniuUpload
PS: 代码很烂,还需要多练
QiniuUpload- 一个方便用七牛做图床然后插入markdown的小工具的更多相关文章
- win10 uwp 使用 asp dotnet core 做图床服务器客户端
原文 win10 uwp 使用 asp dotnet core 做图床服务器客户端 本文告诉大家如何在 UWP 做客户端和 asp dotnet core 做服务器端来做一个图床工具 服务器端 从 ...
- 分享一个超级好用的SM图床
分享一个超级好用的SM图床 大家都知道我是一个喜欢sm Markdown的人,但是Markdown有个很不方便的地方,就是图片的插入,一般用Markdown编辑器(我用的是Typora)直接插入图 ...
- 图床plus演示 | 图床及在线分享演示文稿工具
文章目录 关于图床 什么是图床? 墙内 墙外 关于在线分享演示文稿 在线分享演示文稿 工具分享 待补充 关于图床 什么是图床? 这并不是一个多么高大上的名词概念!用比较通俗的话来说,当你在撰写新文章时 ...
- u-tools图床便捷生成markdown图片
u-tools 图床 上传图片生成markdown图片非常便捷. 支持的图片服务器有几种,其中搜狗.网易和掘金的加载速度更快些: 也可以用阿里与和腾讯云的OSS; 其中网易生成图片不是原图尺寸好像被改 ...
- 使用GitHub API上传文件及GitHub做图床
本文介绍GitHub API基础及上传文件到仓库API,并应用API将GitHub作为图床 GitHub API官方页面 GitHub API版本 当前版本为v3,官方推荐在请求头中显示添加版本标识. ...
- Typora使用教程 之 PicGo集成做图床
目录 一.Typora是什么 二.研究它的原因 三.需要解决的问题 四.解决图床问题 1.下载PicGo 2.安装下载的PicGo,并根据下图所示配置(必须安装nodejs,否则插件一直是" ...
- 自己做的加速app测试流程的小工具,目前打算开放使用,想注册的朋友抓紧了,嘻嘻
为了加速小团队app的测试流程做了这个东西,www.xunce.net 主要特性: web: 一键上传app,方便随时下载 备注测试要点 添加附件,如checklist等文档 自动识别app版本,名 ...
- 在这个插件帮助下,终于用上免费的Https协议外链的图床了
前天,强哥发了一篇推文,讲述了应该如何免费且快速的生成自己的博客网站: 期间也有提到一点就是我们在写博客的时候,因为使用的是Markdown格式的文件,而如果想要Markdown格式的文件在图片上传 ...
- Markdown编辑器及图床推荐
Typora和自动图床工具 Typora 地址 ,极致简洁,界面很漂亮,最重要的是所见即所得 百度云搬运 密码:xi01 自动图床工具 需要七牛云做图床,感谢作者,详见博客 使用方法,只需两步即可完成 ...
随机推荐
- java listener实现定时任务
使用java ServletContextListener 实现各种简单定时任务. 1. 创建ServletContextListener,在3.0版本的web.xml中不再需要添加listener的 ...
- 2.RxJava详解网址http
RxJava 到底是什么 RxJava 好在哪 API 介绍和原理简析 1) Scheduler 的 API (二) 2) Scheduler 的原理(二) 3) 延伸:doOnSubscribe() ...
- iOS分享 - 对象间的通信之delegate、notificationCenter与block
在项目开发中,常常会涉及到对象之间的通信,而为了降低对象间的耦合,会采用delegate.notificationCenter.block三种方式来进行实现,对于他们的使用,也许大家都能熟练掌握,但是 ...
- out返回值的用法与用途
static void Main(string[] arr) { Console.WriteLine("请输入用户名"); string uname = Console.ReadL ...
- jQuery自学笔记(三):jQuery动画效果
jQuery隐藏和显示: 使用 hide( ) 和 show( ) 方法来隐藏和显示 HTML 元素: 语法: $(selector).hide(speed,callback); $(selector ...
- php 初学笔记
1.变量定义和使用 php中定义变量名为:$aa 在类中一般定义一个新变量需要添加var字,如var $aaa. 但是过程或函数中是不需要添加var 关键字,如$aaa=$_POST['aaaa'], ...
- ThinkPHP自动验证
自动验证是ThinkPHP模型层提供的一种数据验证方法,可以在使用create创建数据对象的时候自动进行数据验证. 验证规则 数据验证可以进行数据类型.业务规则.安全判断等方面的验证操作.数据验证有两 ...
- MySQL 查询结果保存为CSV文件
MySQL支持将查询结果直接导出为文本格式,格式如下: into outfile '导出的目录和文件名' 指定导出的目录和文件名 fields terminated ...
- Android学习笔记--Handler用法总结
不错的例子:http://www.cnblogs.com/menlsh/archive/2013/06/07/3125341.html 转自:一叶知秋的博客 http://blog.sina.com. ...
- .NET知识点总结二(笔记整合)
19.什么是类型? 用来定义某一种数据在内存里开辟空间的大小,还可以预置操作此种类型数据的相关方法 20.this关键字在方法中使用时所代表的含义 this指的是当前类的对象,或者父类的类的对象(ba ...