二维码生成工厂
2018-06-22 07:35:44来源:未知 阅读 ()
本次主要分享的是3个免费的二维码接口的对接代码和测试得出的注意点及区别,有更好处理方式多多交流,相互促进进步;最近在学习JavsScript的扩展TypeScript,感觉语法糖很甜,大部分与C#更为类似,可能都是微软项目的原因吧,有兴趣的朋友可以多多相互交流下;
以上是个人的看法,下面来正式分享今天的文章吧:
. Google的Api二维码生成接口
. 2d-code的Api二维码生成接口
. topscan的Api二维码生成接口
. 使用面向对象+加载程序集创建对象合并以上接口封装成二维码生成工厂
下面一步一个脚印的来分享:
. Google的Api二维码生成接口
首先,这里给出Google接口文档的链接qr_codes文档,热情的朋友马上就会打开此链接吧,详细看下里面的参数这就不做截图了,大致通常用到的参数是:api地址,内容参数,生成图片的高宽这3个参数,其他的几个参数都采用默认的吧,不同需要大家可以更详细的看下;其实第一次看到文档里面的参数,感觉少了一些东西,比如怎么不能传递二维码中间那个图标的图片地址和扫描二维码过后怎么跳转到我想重定向的url链接呢,带着这个疑问我进行了多次的尝试;下面给出自己尝试的结果说明:
1. 接口关键参数是:cht(固定值qr),chl(内容参数),chs(生成出来二维码图片尺寸,格式如:200x200,这里是xyz的x不是*)
2. api接口只会生成一个二维码的图片流,如果需要把图片保存到本地需要通过浏览器直接get访问接口或者通过程序下载这个二维码
3. 内容参数如果传递文本信息,在生成出来的二维码图片中间不会显示文本内容,只有用手机扫描二维码才能在手机上显示传递的文本信息
4. 内容参数如果传递单纯的http://格式的链接地址,那么手机扫描后会自动重定向到改http://链接地址上(这个扫描重定向可以用来做一些商品或者文章的查看)
5. google接口暂未研究出此Logo图标地址参数(希望有朋友研究出来后与我分享,谢谢)
6. 由于api地址是国外的,调用接口响应不是那么快速
其次,上面是个人的一些总结,下面我们来看下封装的请求接口方法和下载二维码图片方法:
1 #region 生成二维码 2 3 /// <summary> 4 /// 生成二维码 5 /// </summary> 6 /// <param name="content">展示内容(文本内容 或者 扫描后的跳转http://格式的地址)</param> 7 /// <param name="savePath">保存二维码的磁盘路径(默认程序跟目录+QRCode)</param> 8 /// <param name="logoUrl"> Logo图标地址(格式:http://),(注:google接口暂未研究出此参数)</param> 9 /// <param name="apiUrl">接口地址(内置默认api地址)</param> 10 /// <param name="wAndh">宽度和高度(二维码正方形的,高宽一至,默认200)</param> 11 /// <returns></returns> 12 public virtual string CreateQRCode(string content = null, string savePath = null, string logoUrl = null, string apiUrl = null, int? wAndh = null) 13 { 14 var qrName = string.Empty; 15 16 #region 参数初始化 17 18 ApiUrl = apiUrl ?? ApiUrl; 19 Content = content ?? Content; 20 SaveQRPath = savePath ?? SaveQRPath; 21 LogoUrl = logoUrl ?? LogoUrl; 22 WAndH = wAndh ?? WAndH; 23 #endregion 24 25 if (string.IsNullOrEmpty(ApiUrl)) { return qrName; } 26 27 ApiUrl = string.Format("{0}?cht=qr&chl={1}&chs={2}x{2}", 28 ApiUrl, 29 HttpUtility.UrlEncode(Content), 30 WAndH); 31 32 qrName = DownImg(ApiUrl, SaveQRPath, ImageFormat.Jpeg); 33 return qrName; 34 } 35 #endregion
下载二维码图片保存到程序根目录:
1 #region 下载图片 2 3 /// <summary> 4 /// 下载图片 5 /// </summary> 6 /// <param name="url">图片下载地址</param> 7 /// <param name="savePath">保存路径默认:Img文件夹</param> 8 /// <param name="format">默认:Jpeg</param> 9 /// <returns>新图片名称</returns> 10 public virtual string DownImg(string url, string savePath = "QRCode", ImageFormat format = null) 11 { 12 var qrName = string.Empty; 13 try 14 { 15 format = format ?? ImageFormat.Jpeg; 16 17 HttpClient http = new HttpClient(); 18 http.Timeout = new TimeSpan(0, 1, 0); 19 using (var stream = http.GetStreamAsync(url).Result) 20 { 21 22 if (!Directory.Exists(SaveQRPath)) { Directory.CreateDirectory(SaveQRPath); } 23 qrName = DateTime.Now.ToString("yyyyMMddHHmmssfff") + "." + format; 24 var path = Path.Combine(savePath, qrName); 25 using (Image img = Image.FromStream(stream)) 26 { 27 img.Save(path, format); 28 } 29 } 30 } 31 catch (Exception ex) 32 { 33 qrName = string.Empty; 34 } 35 return qrName; 36 } 37 #endregion
上面两个方法使用的是虚方法,因为我这里是吧google接口当做默认的二维码生成器来使用,后面要讲的另外两个接口都是重写与此;下载图片的方法都是公用的,暂不需要重写;这里需要提到的是调用api接口时有一个固定的参数cht=qr,这个参数表示采用QR方法生成二维码,因为这个api接口还有生成图标的功能,所以只想要生成二维码这里就固定,更多的生成图标功能不在本章分享中,谢谢。
. 2d-code的Api二维码生成接口
首先,该接口需要通过他们官网注册一个key,然后从后台获取到这个key后才能调用接口地址,当然注册后有个功能是,凡是您通过api接口生成的二维码,除了自己通过流下载,还能通过他们后台一起下载所有生成的图片,本人暂时没有去关注是否生成量大了会收费哈哈,下面列举下接口参数说明和测试得出的注意点:
1. 接口关键参数是:key(注册获取),text(文本参数),url(扫描后重定向地址),logo(Logo图标地址),size(二维码正方形,高宽)
2. 接口的文本参数只能传递文本,不能当做扫描后重定向的地址参数使用和Google等接口有点不一样
3. 扫描后重定向地址和Logo图标地址都是可访问的http://格式的地址链接
4. Logo图标地址,官方说不建议使用png格式,测试只有jpg成功(可能是测试不够多这里只单纯介绍我的结果)
5. 生成速度比较快,而且还有一个艺术字的生成接口,挺不错
6. api接口只会生成一个二维码的图片流,如果需要把图片保存到本地需要通过浏览器直接get访问接口或者通过程序下载这个二维码
其次,下面给出封装的代码,由于下载和上面介绍的代码一样是公用的这里就不做陈述:
1 public QR_2dCode() 2 { 3 4 ApiUrl = "http://www.2d-code.cn/2dcode/api.php"; 5 } 6 7 #region 生成二维码 8 9 /// <summary> 10 /// 生成二维码 11 /// </summary> 12 /// <param name="content">展示内容(文本内容 或者 扫描后的跳转http://格式的地址)</param> 13 /// <param name="savePath">保存二维码的磁盘路径(默认程序跟目录+QRCode)</param> 14 /// <param name="logoUrl"> Logo图标地址(格式:http://),官方不建议使用png格式,测试只有jpg成功</param> 15 /// <param name="directUrl">扫描后重定向地址(http://)</param> 16 /// <param name="apiUrl">接口地址(内置默认api地址)</param> 17 /// <param name="wAndh">宽度和高度(二维码正方形的,高宽一至,默认200)</param> 18 /// <returns></returns> 19 public override string CreateQRCode(string content = null, string savePath = null, string logoUrl = null, string apiUrl = null, int? wAndh = null) 20 { 21 var qrName = string.Empty; 22 23 #region 参数初始化 24 25 ApiUrl = apiUrl ?? ApiUrl; 26 Content = content ?? Content; 27 SaveQRPath = savePath ?? SaveQRPath; 28 LogoUrl = logoUrl ?? LogoUrl; 29 WAndH = wAndh ?? WAndH; 30 #endregion 31 32 if (string.IsNullOrEmpty(ApiUrl)) { return qrName; } 33 34 ApiUrl = string.Format("{0}?key=c_d800OBbu6hDzJtXPE2Yd02IMtmpuK9VdCqHe6vrtar4&text={1}&url={2}&logo={3}&size={4}", 35 ApiUrl, 36 HttpUtility.UrlEncode(Content.Contains("http") ? "" : Content), 37 HttpUtility.UrlEncode(Content), 38 HttpUtility.UrlEncode(LogoUrl), 39 WAndH); 40 41 qrName = DownImg(ApiUrl, SaveQRPath); 42 return qrName; 43 } 44 #endregion
. topscan的Api二维码生成接口
首先,该接口肯定是免费的,参数描述和google的差不多,不同处在于可以传递Logo图标地址(当然可能我还没发现google的可以传递logo的参数,故此朋友们可以忽略);下面列举下接口参数说明和测试得出的注意点:
1. 接口关键参数是:text(内容参数),logo(Logo图标地址),w(生成出来二维码图片尺寸,格式如:200x200,这里是xyz的x不是*)
2. api接口只会生成一个二维码的图片流,如果需要把图片保存到本地需要通过浏览器直接get访问接口或者通过程序下载这个二维码
3. 内容参数如果传递文本信息,在生成出来的二维码图片中间不会显示文本内容,只有用手机扫描二维码才能在手机上显示传递的文本信息
4. 内容参数如果传递单纯的http://格式的链接地址,那么手机扫描后会自动重定向到改http://链接地址上(这个扫描重定向可以用来做一些商品或者文章的查看)
5. Logo图标地址(格式:http://),jpg,png测试通过
6. 测试得出有时候请求生成二维码不返回数据,有可能是我网路问题吧,正常生成二维码的速度还是挺快
其次,下面给出封装的代码,由于下载和上面介绍的代码一样是公用的这里就不做陈述:
1 public QR_TopScan() 2 { 3 4 ApiUrl = "http://qr.topscan.com/api.php"; 5 } 6 7 #region 生成二维码 8 9 /// <summary> 10 /// 生成二维码 11 /// </summary> 12 /// <param name="content">展示内容(文本内容 或者 扫描后的跳转http://格式的地址)</param> 13 /// <param name="savePath">保存二维码的磁盘路径(默认程序跟目录+QRCode)</param> 14 /// <param name="logoUrl"> Logo图标地址(格式:http://),jpg,png测试通过,测试得出有不能成功的,原因不知是否和地址有关</param> 15 /// <param name="apiUrl">接口地址(内置默认api地址)</param> 16 /// <param name="wAndh">宽度和高度(二维码正方形的,高宽一至,默认200)</param> 17 /// <returns></returns> 18 public override string CreateQRCode(string content = null, string savePath = null, string logoUrl = null, string apiUrl = null, int? wAndh = null) 19 { 20 var qrName = string.Empty; 21 22 #region 参数初始化 23 24 ApiUrl = apiUrl ?? ApiUrl; 25 Content = content ?? Content; 26 SaveQRPath = savePath ?? SaveQRPath; 27 LogoUrl = logoUrl ?? LogoUrl; 28 WAndH = wAndh ?? WAndH; 29 #endregion 30 31 if (string.IsNullOrEmpty(ApiUrl)) { return qrName; } 32 33 ApiUrl = string.Format("{0}?text={1}&logo={2}&w={3}", 34 ApiUrl, 35 HttpUtility.UrlEncode(Content), 36 HttpUtility.UrlEncode(LogoUrl), 37 WAndH); 38 39 qrName = DownImg(ApiUrl, SaveQRPath); 40 return qrName; 41 } 42 #endregion
. 使用面向对象+加载程序集创建对象合并以上接口封装成二维码生成工厂
首先,分析上面3个接口的参数可以看出,都需要固定的参数:接口api,内容(文本或跳转http地址),Logo图片地址(google暂时除外),宽度和高度等这几个参数,这样一来咋们可以定义个统一参数类,来传递该参数信息,这里还要提下由于这几个接口都是从别人接口获取图片流,如果想要吧图片在执行程序时候直接保存在我们的程序本地,都需要下载,所以又多一个参数: 保存二维码的磁盘路径,所以才有了一下公共的属性:
1 #region 基础配置信息 2 3 /// <summary> 4 /// 接口地址(必填) 5 /// </summary> 6 protected string ApiUrl = "https://chart.googleapis.com/chart"; 7 8 /// <summary> 9 /// 展示内容(文本内容),google文本参数直接传递http地址直接重定向 10 /// </summary> 11 protected string Content = "http://www.cnblogs.com/wangrudong003/"; 12 13 /// <summary> 14 /// 保存二维码的磁盘路径(默认程序跟目录+QRCode) 15 /// </summary> 16 protected string SaveQRPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "QRCode"); 17 18 /// <summary> 19 /// Logo图片地址(http://) 20 /// </summary> 21 protected string LogoUrl = "http://a.hiphotos.baidu.com/baike/w%3D268%3Bg%3D0/sign=9a34e44d8bd4b31cf03c93bdbfed4042/2cf5e0fe9925bc318cb9fe965edf8db1ca1370dc.jpg"; 22 23 /// <summary> 24 /// 宽度和高度(二维码正方形的,高宽一至,默认200) 25 /// </summary> 26 protected int WAndH = 200; 27 28 #endregion
然后,这里我不想每个接口都手动new一次来创建对象,所以用了加载程序集的模块的方式来创建所需要的对象,因此有了工厂类的入口:
1 /// <summary> 2 /// 二维码生成工厂 3 /// </summary> 4 public class QRCodeReposity 5 { 6 7 public static BaseQRCode Current(QREmType qrEmType = QREmType.BaseQRCode) 8 { 9 10 var nspace = typeof(BaseQRCode); 11 var fullName = nspace.FullName; 12 var nowspace = fullName.Substring(0, fullName.LastIndexOf('.') + 1); 13 14 return Assembly.GetExecutingAssembly().CreateInstance(nowspace + qrEmType.ToString(), true) as BaseQRCode; 15 } 16 }
这里和之前的缓存工厂文章设计差不多,可以查阅下之前的分享篇,也多多点赞,谢谢;下面在给出说有的代码如下:
1 /// <summary> 2 /// 工厂模块定义 3 /// </summary> 4 public enum QREmType 5 { 6 /// <summary> 7 /// google接口 8 /// </summary> 9 BaseQRCode, 10 11 /// <summary> 12 /// 2d-code接口 13 /// </summary> 14 QR_2dCode, 15 16 /// <summary> 17 /// topscan接口 18 /// </summary> 19 QR_TopScan 20 } 21 22 /// <summary> 23 /// 二维码生成工厂 24 /// </summary> 25 public class QRCodeReposity 26 { 27 28 public static BaseQRCode Current(QREmType qrEmType = QREmType.BaseQRCode) 29 { 30 31 var nspace = typeof(BaseQRCode); 32 var fullName = nspace.FullName; 33 var nowspace = fullName.Substring(0, fullName.LastIndexOf('.') + 1); 34 35 return Assembly.GetExecutingAssembly().CreateInstance(nowspace + qrEmType.ToString(), true) as BaseQRCode; 36 } 37 } 38 39 /// <summary> 40 /// 基类使用Google提供Api:https://developers.google.com/chart/infographics/docs/qr_codes ,由于是国外地址,相对来说有点慢 41 /// </summary> 42 public class BaseQRCode 43 { 44 45 #region 基础配置信息 46 47 /// <summary> 48 /// 接口地址(必填) 49 /// </summary> 50 protected string ApiUrl = "https://chart.googleapis.com/chart"; 51 52 /// <summary> 53 /// 展示内容(文本内容),google文本参数直接传递http地址直接重定向 54 /// </summary> 55 protected string Content = "http://www.cnblogs.com/wangrudong003/"; 56 57 /// <summary> 58 /// 保存二维码的磁盘路径(默认程序跟目录+QRCode) 59 /// </summary> 60 protected string SaveQRPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "QRCode"); 61 62 /// <summary> 63 /// Logo图片地址(http://) 64 /// </summary> 65 protected string LogoUrl = "http://a.hiphotos.baidu.com/baike/w%3D268%3Bg%3D0/sign=9a34e44d8bd4b31cf03c93bdbfed4042/2cf5e0fe9925bc318cb9fe965edf8db1ca1370dc.jpg"; 66 67 /// <summary> 68 /// 宽度和高度(二维码正方形的,高宽一至,默认200) 69 /// </summary> 70 protected int WAndH = 200; 71 72 #endregion 73 74 #region 方法 75 76 #region 生成二维码 77 78 /// <summary> 79 /// 生成二维码 80 /// </summary> 81 /// <param name="content">展示内容(文本内容 或者 扫描后的跳转http://格式的地址)</param> 82 /// <param name="savePath">保存二维码的磁盘路径(默认程序跟目录+QRCode)</param> 83 /// <param name="logoUrl"> Logo图标地址(格式:http://),(注:google接口暂未研究出此参数)</param> 84 /// <param name="apiUrl">接口地址(内置默认api地址)</param> 85 /// <param name="wAndh">宽度和高度(二维码正方形的,高宽一至,默认200)</param> 86 /// <returns></returns> 87 public virtual string CreateQRCode(string content = null, string savePath = null, string logoUrl = null, string apiUrl = null, int? wAndh = null) 88 { 89 var qrName = string.Empty; 90 91 #region 参数初始化 92 93 ApiUrl = apiUrl ?? ApiUrl; 94 Content = content ?? Content; 95 SaveQRPath = savePath ?? SaveQRPath; 96 LogoUrl = logoUrl ?? LogoUrl; 97 WAndH = wAndh ?? WAndH; 98 #endregion 99 100 if (string.IsNullOrEmpty(ApiUrl)) { return qrName; } 101 102 ApiUrl = string.Format("{0}?cht=qr&chl={1}&chs={2}x{2}", 103 ApiUrl, 104 HttpUtility.UrlEncode(Content), 105 WAndH); 106 107 qrName = DownImg(ApiUrl, SaveQRPath, ImageFormat.Jpeg); 108 return qrName; 109 } 110 #endregion 111 112 #region 下载图片 113 114 /// <summary> 115 /// 下载图片 116 /// </summary> 117 /// <param name="url">图片下载地址</param> 118 /// <param name="savePath">保存路径默认:Img文件夹</param> 119 /// <param name="format">默认:Jpeg</param> 120 /// <returns>新图片名称</returns> 121 public virtual string DownImg(string url, string savePath = "QRCode", ImageFormat format = null) 122 { 123 var qrName = string.Empty; 124 try 125 { 126 format = format ?? ImageFormat.Jpeg; 127 128 HttpClient http = new HttpClient(); 129 http.Timeout = new TimeSpan(0, 1, 0); 130 using (var stream = http.GetStreamAsync(url).Result) 131 { 132 133 if (!Directory.Exists(SaveQRPath)) { Directory.CreateDirectory(SaveQRPath); } 134 qrName = DateTime.Now.ToString("yyyyMMddHHmmssfff") + "." + format; 135 var path = Path.Combine(savePath, qrName); 136 using (Image img = Image.FromStream(stream)) 137 { 138 img.Save(path, format); 139 } 140 } 141 } 142 catch (Exception ex) 143 { 144 qrName = string.Empty; 145 } 146 return qrName; 147 } 148 #endregion 149 150 #endregion 151 } 152 153 /// <summary> 154 /// 使用2d-code提供Api,需要去官网注册获取Key 155 /// </summary> 156 public class QR_2dCode : BaseQRCode 157 { 158 159 public QR_2dCode() 160 { 161 162 ApiUrl = "http://www.2d-code.cn/2dcode/api.php"; 163 } 164 165 #region 生成二维码 166 167 /// <summary> 168 /// 生成二维码 169 /// </summary> 170 /// <param name="content">展示内容(文本内容 或者 扫描后的跳转http://格式的地址)</param> 171 /// <param name="savePath">保存二维码的磁盘路径(默认程序跟目录+QRCode)</param> 172 /// <param name="logoUrl"> Logo图标地址(格式:http://),官方不建议使用png格式,测试只有jpg成功</param> 173 /// <param name="directUrl">扫描后重定向地址(http://)</param> 174 /// <param name="apiUrl">接口地址(内置默认api地址)</param> 175 /// <param name="wAndh">宽度和高度(二维码正方形的,高宽一至,默认200)</param> 176 /// <returns></returns> 177 public override string CreateQRCode(string content = null, string savePath = null, string logoUrl = null, string apiUrl = null, int? wAndh = null) 178 { 179 var qrName = string.Empty; 180 181 #region 参数初始化 182 183 ApiUrl = apiUrl ?? ApiUrl; 184 Content = content ?? Content; 185 SaveQRPath = savePath ?? SaveQRPath; 186 LogoUrl = logoUrl ?? LogoUrl; 187 WAndH = wAndh ?? WAndH; 188 #endregion 189 190 if (string.IsNullOrEmpty(ApiUrl)) { return qrName; } 191 192 ApiUrl = string.Format("{0}?key=c_d800OBbu6hDzJtXPE2Yd02IMtmpuK9VdCqHe6vrtar4&text={1}&url={2}&logo={3}&size={4}", 193 ApiUrl, 194 HttpUtility.UrlEncode(Content.Contains("http") ? "" : Content), 195 HttpUtility.UrlEncode(Content), 196 HttpUtility.UrlEncode(LogoUrl), 197 WAndH); 198 199 qrName = DownImg(ApiUrl, SaveQRPath); 200 return qrName; 201 } 202 #endregion 203 } 204 205 /// <summary> 206 /// 使用topscan提供Api 207 /// </summary> 208 public class QR_TopScan : BaseQRCode 209 { 210 211 public QR_TopScan() 212 { 213 214 ApiUrl = "http://qr.topscan.com/api.php"; 215 } 216 217 #region 生成二维码 218 219 /// <summary> 220 /// 生成二维码 221 /// </summary> 222 /// <param name="content">展示内容(文本内容 或者 扫描后的跳转http://格式的地址)</param> 223 /// <param name="savePath">保存二维码的磁盘路径(默认程序跟目录+QRCode)</param> 224 /// <param name="logoUrl"> Logo图标地址(格式:http://),jpg,png测试通过,测试得出有不能成功的,原因不知是否和地址有关</param> 225 /// <param name="apiUrl">接口地址(内置默认api地址)</param> 226 /// <param name="wAndh">宽度和高度(二维码正方形的,高宽一至,默认200)</param> 227 /// <returns></returns> 228 public override string CreateQRCode(string content = null, string savePath = null, string logoUrl = null, string apiUrl = null, int? wAndh = null) 229 { 230 var qrName = string.Empty; 231 232 #region 参数初始化 233 234 ApiUrl = apiUrl ?? ApiUrl; 235 Content = content ?? Content; 236 SaveQRPath = savePath ?? SaveQRPath; 237 LogoUrl = logoUrl ?? LogoUrl; 238 WAndH = wAndh ?? WAndH; 239 #endregion 240 241 if (string.IsNullOrEmpty(ApiUrl)) { return qrName; } 242 243 ApiUrl = string.Format("{0}?text={1}&logo={2}&w={3}", 244 ApiUrl, 245 HttpUtility.UrlEncode(Content), 246 HttpUtility.UrlEncode(LogoUrl), 247 WAndH); 248 249 qrName = DownImg(ApiUrl, SaveQRPath); 250 return qrName; 251 } 252 #endregion 253 }
本篇的分享内容在程序设计方面没有太多,重点是分装下这几个接口和分享下接口的差异,方面朋友们可以拿来主义和正在对接二维码生成的朋友做下交流,仅此而已;关键代码的备注都在分享代码里,有更好或者不清楚的地方欢迎留言,谢谢,放一张效果图,大家可以扫一扫:
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- .NET随机数函数的生成方法 2020-03-18
- ASP.NET编程简单实现生成静态页面的方法 2020-02-06
- MVC生成页码选择器返回HTML代码详解 2020-02-06
- asp.net实现生成静态页并添加链接的方法 2019-12-15
- 总结ASP.NET生成二维码的方法 2019-11-21
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash