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
}
}