我使用据说是Windows下最好用的Markdown编辑器“MarkdownPad2”(个人感觉还是Visual Code+Markdown插件666)写Markdown,在贴图方面遇到一个问题,于是找到了网易云的免费OSS服务,并编写了一个小工具来管理图床(网易云OSS)。
Markdown写文档很爽,这里不多说了;网易云OSS免费服务的介绍去官网看就可以了,https://www.163yun.com。
50GB免费存储空间
每月100万次免费GET请求
每月20GB免费下行流量
每月10万次免费PUT请求
这个免费额度还是很大的,业界良心,比七牛云要强多了。
————————————————————————————————————————————————————————————————————————————
分割线,下边说正题
————————————————————————————————————————————————————————————————————————————
上图是我写的小工具的截图,起初我使用QQ截图后,需要:
- 保存到磁盘
- MarkdownPad上传图片(当然,后来也不能用了)
MarkdownPad使用一国外网站做图床,每个MarkdownPad账户仅能上传有限个数的图片(据说破解版可以无限制上传,可能我用的版本破解的不够彻底吧),因此用了一阵子后再也不能贴图了(其实这个国外网站贴图很慢的)。
于是开始寻觅免费图床,很多图床的免费服务都有限制,比如图片个数、保存时限,更重要的是一些小图床不知道过多久就关门大吉了。
有朋友使用GitHub做图床,我没有试过,我使用了开源中国(OSChina)的码云做图床,但图片存储的是Base64编码,太占地方了。
后来我找到了网易云的OSS服务,免费注册认证过后,按照SDK编写了接口程序(网易云的C#示例代码竟然有错误语法,好粗心。。。)。
有了这个小工具后,我使用QQ截图后,直接在Markdown中Ctrl+V即可,方便多了。
贴个小图,求打赏。
下载链接(百度云盘):https://pan.baidu.com/s/1jKcQl5W 密码:hxad
使用时,配置注册的网易云OSS的endpoint和accessKeyId、accessKeySecret,以及创建的bucket名称。
另外两个参数对应于程序窗体的复选框。
——————————————————————————————————————————————————————————————————
没代码的工具,不应该贴在博客园里,下边附上关键代码
——————————————————————————————————————————————————————————————————
阿里云OSS辅助类,实现阿里云OSS接口,摘抄自阿里云帮助文档。
1 using Netease.Cloud.NOS; 2 using System; 3 using System.Collections.Generic; 4 using System.Linq; 5 using System.Text; 6 using System.Threading.Tasks; 7 8 namespace Eyuan._163Yun.Lib 9 { 10 public class YunHelper 11 { 12 #region 配置 13 public static string endpoint = "nos-eastchina1.126.net"; 14 public static string accessKeyId = ""; 15 public static string accessKeySecret = ""; 16 public static NosClient nosClient = null; 17 // 18 public static string bucket = "dump"; 19 /// <summary> 20 /// 初始化 NosClient 21 /// </summary> 22 public static void InitClient() 23 { 24 // 25 InitConfig(); 26 // 27 ClientConfiguration conf = new ClientConfiguration(); 28 // 设置NosClient连接超时时间,单位:毫秒 29 conf.ConnectionTimeout = 50000; 30 // 设置NosClient使用的最大连接数 31 //conf.MaxConnections(200); 32 // 设置socket超时时间,单位:毫秒 33 //conf.SocketTimeout(10000); 34 // 设置失败请求重试次数 35 //conf.MaxErrorRetry(2); 36 //nosClient = new NosClient(endpoint, accessKeyId, accessKeySecret); 37 if (string.IsNullOrEmpty(endpoint) || string.IsNullOrEmpty(accessKeyId) || string.IsNullOrEmpty(accessKeySecret)) 38 { 39 return; 40 } 41 nosClient = new NosClient(endpoint, accessKeyId, accessKeySecret, conf); 42 } 43 private static void InitConfig() 44 { 45 endpoint = ConfigHelper.Endpoint; 46 accessKeyId = System.Configuration.ConfigurationManager.AppSettings["accessKeyId"]; 47 accessKeySecret = System.Configuration.ConfigurationManager.AppSettings["accessKeySecret"]; 48 bucket = ConfigHelper.Bucket; 49 } 50 #endregion 51 52 #region 上传文件 53 /// <summary> 54 /// 上传文件 55 /// </summary> 56 /// <param name="bucket">桶名</param> 57 /// <param name="key">对象名</param> 58 /// <param name="fileToUpload">上传的文件</param> 59 public static void PutObject(string bucket, string key, string fileToUpload) 60 { 61 try 62 { 63 nosClient.PutObject(bucket, key, fileToUpload); 64 Console.WriteLine("Put object:{0} succeeded", key); 65 } 66 catch (NosException ex) 67 { 68 Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}", 69 ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource); 70 } 71 catch (Exception ex) 72 { 73 Console.WriteLine("Failed with error info: {0}", ex.Message); 74 } 75 } 76 #endregion 77 78 #region 下载文件 79 /// <summary> 80 /// 下载文件 81 /// </summary> 82 /// <param name="bucket">桶名</param> 83 /// <param name="key">对象名</param> 84 /// <param name="dirToDownload">下载文件存放的目录</param> 85 public static void GetObject(string bucket, string key, string dirToDownload) 86 { 87 try 88 { 89 nosClient.GetObject(bucket, key, dirToDownload + "/sample.data"); 90 Console.WriteLine("Get object succeeded"); 91 } 92 catch (NosException ex) 93 { 94 Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}", 95 ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource); 96 } 97 catch (Exception ex) 98 { 99 Console.WriteLine("Failed with error info: {0}", ex.Message); 100 } 101 } 102 #endregion 103 104 #region 列举桶内文件 105 /// <summary> 106 /// 列举桶内文件 107 /// </summary> 108 /// <param name="bucket">桶名</param> 109 public static void ListObjects(string bucket) 110 { 111 try 112 { 113 var keys = new List<string>(); 114 var listObjectsRequest = new ListObjectsRequest(bucket); 115 ObjectListing result = nosClient.ListObjects(listObjectsRequest); 116 foreach (var summary in result.ObjectSummarise) 117 { 118 Console.WriteLine(summary.Key); 119 keys.Add(summary.Key); 120 } 121 122 Console.WriteLine("List objects of bucket:{0} succeeded ", bucket); 123 } 124 catch (NosException ex) 125 { 126 Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}", 127 ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource); 128 } 129 catch (Exception ex) 130 { 131 Console.WriteLine("Failed with error info: {0}", ex.Message); 132 } 133 } 134 #endregion 135 136 #region 删除单个文件 137 /// <summary> 138 /// 删除单个文件 139 /// </summary> 140 /// <param name="bucket">桶名</param> 141 /// <param name="key">对象名</param> 142 public static void DeleteObject(string bucket, string key) 143 { 144 try 145 { 146 nosClient.DeleteObject(bucket, key); 147 Console.WriteLine("Delete object succeeded"); 148 } 149 catch (NosException ex) 150 { 151 Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}", 152 ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource); 153 } 154 catch (Exception ex) 155 { 156 Console.WriteLine("Failed with error info: {0}", ex.Message); 157 } 158 } 159 #endregion 160 161 } 162 }