using Masuit.Tools.Core.Config; using Masuit.Tools.Core.NoSQL; using Masuit.Tools.Logging; using Masuit.Tools.Models; using Masuit.Tools.NoSQL; using Microsoft.AspNetCore.Http; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.Http; using System.Net.Http.Headers; using System.Threading.Tasks; namespace Masuit.Tools.Core.Net { /// /// Web操作扩展 /// public static class WebExtension { #region 获取线程内唯一的EF上下文对象 /// /// 获取线程内唯一的EF上下文对象,.NetCore中获取EF数据上下文对象,需要通过依赖注入的方式,请考虑在自己的项目中通过Masuit.Tools提供的CallContext对象实现获取线程内唯一的EF上下文对象,示例代码: /// public static DataContext GetDbContext() /// { /// DataContext db; /// if (CallContext<DataContext>.GetData("db") is null) /// { /// DbContextOptions<DataContext> dbContextOption = new DbContextOptions<DataContext>(); /// DbContextOptionsBuilder<DataContext> dbContextOptionBuilder = new DbContextOptionsBuilder<DataContext>(dbContextOption); /// db = new DataContext(dbContextOptionBuilder.UseSqlServer(CommonHelper.ConnectionString).Options); /// CallContext<DataContext>.SetData("db", db); /// } /// db = CallContext<DataContext>.GetData("db"); /// return db; /// } /// /// EF上下文容器对象 /// EF上下文容器对象 [Obsolete(@".NetCore中获取EF数据上下文对象,需要通过依赖注入的方式,请考虑在自己的项目中通过Masuit.Tools提供的CallContext对象实现获取线程内唯一的EF上下文对象,示例代码: public static DataContext GetDbContext() { DataContext db; if (CallContext.GetData(""db"") is null) { DbContextOptions dbContextOption = new DbContextOptions(); DbContextOptionsBuilder dbContextOptionBuilder = new DbContextOptionsBuilder(dbContextOption); db = new DataContext(dbContextOptionBuilder.UseSqlServer(CommonHelper.ConnectionString).Options); CallContext.SetData(""db"", db); } db = CallContext.GetData(""db""); return db; }")] public static T GetDbContext() where T : new() { throw new Exception(@".NetCore中获取EF数据上下文对象,需要通过依赖注入的方式,请考虑在自己的项目中通过Masuit.Tools提供的CallContext对象实现获取线程内唯一的EF上下文对象,示例代码: public static DataContext GetDbContext() { DataContext db; if (CallContext.GetData(""db"") is null) { DbContextOptions dbContextOption = new DbContextOptions(); DbContextOptionsBuilder dbContextOptionBuilder = new DbContextOptionsBuilder(dbContextOption); db = new DataContext(dbContextOptionBuilder.UseSqlServer(CommonHelper.ConnectionString).Options); CallContext.SetData(""db"", db); } db = CallContext.GetData(""db""); return db; } "); } #endregion #region 获取客户端IP地址信息 /// /// 根据IP地址获取详细地理信息 /// /// /// public static async Task>> GetIPAddressInfo(this string ip) { ip.MatchInetAddress(out var isIpAddress); if (isIpAddress) { var address = await GetPhysicsAddressInfo(ip); if (address.Status == 0) { string detail = $"{address.AddressResult.FormattedAddress} {address.AddressResult.AddressComponent.Direction}{address.AddressResult.AddressComponent.Distance ?? "0"}米"; List pois = address.AddressResult.Pois.Select(p => $"{p.AddressDetail}{p.Name} {p.Direction}{p.Distance ?? "0"}米").ToList(); return new Tuple>(detail, pois); } return new Tuple>("IP地址不正确", new List()); } return new Tuple>($"{ip}不是一个合法的IP地址", new List()); } /// /// 根据IP地址获取详细地理信息对象 /// /// /// public static async Task GetPhysicsAddressInfo(this string ip) { ip.MatchInetAddress(out var isIpAddress); if (isIpAddress) { string ak = CoreConfig.Configuration["AppSettings:BaiduAK"]; if (string.IsNullOrEmpty(ak)) { throw new Exception("未配置BaiduAK,请先在您的应用程序web.config或者App.config中的AppSettings节点下添加BaiduAK配置节(注意大小写)"); } using (HttpClient client = new HttpClient() { BaseAddress = new Uri("http://api.map.baidu.com") }) { client.DefaultRequestHeaders.Referrer = new Uri("http://lbsyun.baidu.com/jsdemo.htm"); var task = client.GetAsync($"/location/ip?ak={ak}&ip={ip}&coor=bd09ll").ContinueWith(async t => { if (t.IsFaulted || t.IsCanceled) { return null; } var res = await t; if (res.IsSuccessStatusCode) { var ipAddress = JsonConvert.DeserializeObject(await res.Content.ReadAsStringAsync()); if (ipAddress.Status == 0) { LatiLongitude point = ipAddress.AddressInfo.LatiLongitude; string result = client.GetStringAsync($"/geocoder/v2/?location={point.Y},{point.X}&output=json&pois=1&radius=1000&latest_admin=1&coordtype=bd09ll&ak={ak}").Result; PhysicsAddress address = JsonConvert.DeserializeObject(result); if (address.Status == 0) { return address; } } else { using (var client2 = new HttpClient { BaseAddress = new Uri("http://ip.taobao.com") }) { return await await client2.GetAsync($"/service/getIpInfo.php?ip={ip}").ContinueWith(async tt => { if (tt.IsFaulted || tt.IsCanceled) { return null; } var result = await tt; if (result.IsSuccessStatusCode) { TaobaoIP taobaoIp = JsonConvert.DeserializeObject(await result.Content.ReadAsStringAsync()); if (taobaoIp.Code == 0) { return new PhysicsAddress() { Status = 0, AddressResult = new AddressResult() { FormattedAddress = taobaoIp.IpData.Country + taobaoIp.IpData.Region + taobaoIp.IpData.City, AddressComponent = new AddressComponent() { Province = taobaoIp.IpData.Region }, Pois = new List() } }; } } return null; }); } } } return null; }); return await await task; } } return null; } /// /// 根据IP地址获取ISP /// /// /// public static string GetISP(this string ip) { if (ip.MatchInetAddress()) { using (var client = new HttpClient { BaseAddress = new Uri("http://ip.taobao.com") }) { var task = client.GetAsync($"/service/getIpInfo.php?ip={ip}").ContinueWith(async t => { if (t.IsFaulted) { return $"未能找到{ip}的ISP信息"; } var result = await t; if (result.IsSuccessStatusCode) { TaobaoIP taobaoIp = JsonConvert.DeserializeObject(await result.Content.ReadAsStringAsync()); if (taobaoIp.Code == 0) { return taobaoIp.IpData.Isp; } } return $"未能找到{ip}的ISP信息"; }); return task.Result.Result; } } return $"{ip}不是一个合法的IP"; } #endregion /// /// 上传图片到百度图床 /// /// /// public static async Task UploadImageAsync(Stream stream) { using (HttpClient httpClient = new HttpClient() { BaseAddress = new Uri("https://sp1.baidu.com"), }) { httpClient.DefaultRequestHeaders.UserAgent.Add(ProductInfoHeaderValue.Parse("Mozilla/5.0")); using (var bc = new StreamContent(stream)) { bc.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = "1.jpg", Name = "image" }; bc.Headers.ContentType = MediaTypeHeaderValue.Parse("image/jpeg"); using (var content = new MultipartFormDataContent { bc }) { return await await httpClient.PostAsync("/70cHazva2gU2pMbgoY3K/n/image?needJson=true", content).ContinueWith(async t => { if (t.IsCanceled || t.IsFaulted) { Console.WriteLine("发送请求出错了" + t.Exception); return string.Empty; } var res = await t; if (res.IsSuccessStatusCode) { string s = await res.Content.ReadAsStringAsync(); var token = JObject.Parse(s); if ((int)token["errno"] == 0) { s = (string)token["data"]["imageUrl"]; return s; } s = (string)token["errmsg"]; return s; } return string.Empty; }); } } } } #region 写Session /// /// 写Session /// /// /// 键 /// 值 public static void Set(this ISession session, string key, object value) { session.SetString(key, value.ToJsonString()); } /// /// 将Session存到Redis,需要先在config中配置链接字符串,连接字符串在config配置文件中的ConnectionStrings节下配置,name固定为RedisHosts,值的格式:127.0.0.1:6379,allowadmin=true,若未正确配置,将按默认值“127.0.0.1:6379,allowadmin=true”进行操作,如:
/// <connectionStrings>
/// <add name = "RedisHosts" connectionString="127.0.0.1:6379,allowadmin=true"/>
/// </connectionStrings> ///
/// /// /// 键 /// 需要存的对象 /// 过期时间,默认20分钟 /// public static void SetByRedis(this ISession session, string key, T obj, int expire = 20) { if (HttpContext2.Current is null) { throw new Exception("请确保此方法调用是在同步线程中执行!"); } session?.SetString(key, obj.ToJsonString()); try { using (RedisHelper redisHelper = RedisHelper.GetInstance(RedisHelperFactory.ConnectionCache.Values.FirstOrDefault() ?? throw new ArgumentException("在使用该方法之前,请先在Startup.cs中配置services.AddxxxRedisHelper"), 1)) { redisHelper.SetHash("Session:" + HttpContext2.Current.Connection.Id, key, obj, TimeSpan.FromMinutes(expire)); //存储数据到缓存服务器,这里将字符串"my value"缓存,key 是"test" } } catch { // ignored } } #endregion #region 获取Session /// /// 获取Session /// /// 对象 /// /// 键 /// 对象 public static T Get(this ISession session, string key) { string value = session.GetString(key); if (string.IsNullOrEmpty(value)) { return default(T); } return JsonConvert.DeserializeObject(value); } /// /// 从Redis取Session /// /// /// /// 键 /// 过期时间,默认20分钟 /// public static T GetByRedis(this ISession _, string key, int expire = 20) where T : class { if (HttpContext2.Current is null) { throw new Exception("请确保此方法调用是在同步线程中执行!"); } T obj = default(T); if (_ != null) { obj = _.Get(key); } if (obj == default(T)) { try { var sessionKey = "Session:" + HttpContext2.Current.Connection.Id; using (RedisHelper redisHelper = RedisHelper.GetInstance(RedisHelperFactory.ConnectionCache.Values.FirstOrDefault() ?? throw new ArgumentException("在使用该方法之前,请先在Startup.cs中配置services.AddxxxRedisHelper"), 1)) { if (redisHelper.KeyExists(sessionKey) && redisHelper.HashExists(sessionKey, key)) { redisHelper.Expire(sessionKey, TimeSpan.FromMinutes(expire)); return redisHelper.GetHash(sessionKey, key); } return default(T); } } catch { return default(T); } } return obj; } /// /// 从Redis移除对应键的Session /// /// /// /// public static void RemoveByRedis(this ISession session, string key) { if (HttpContext2.Current is null) { throw new Exception("请确保此方法调用是在同步线程中执行!"); } session?.Remove(key); try { var sessionKey = "Session:" + HttpContext2.Current.Connection.Id; using (RedisHelper redisHelper = RedisHelper.GetInstance(RedisHelperFactory.ConnectionCache.Values.FirstOrDefault() ?? throw new ArgumentException("在使用该方法之前,请先在Startup.cs中配置services.AddxxxRedisHelper"), 1)) { if (redisHelper.KeyExists(sessionKey) && redisHelper.HashExists(sessionKey, key)) { redisHelper.DeleteHash(sessionKey, key); } } } catch (Exception e) { LogManager.Error(e); } } /// /// Session个数 /// /// /// public static int SessionCount(this ISession session) { try { using (RedisHelper redisHelper = RedisHelper.GetInstance(RedisHelperFactory.ConnectionCache.Values.FirstOrDefault() ?? throw new ArgumentException("在使用该方法之前,请先在Startup.cs中配置services.AddxxxRedisHelper"), 1)) { return redisHelper.GetServer().Keys(1, "Session:*").Count(); } } catch (Exception e) { LogManager.Error(e); return 0; } } #endregion } }