@@ -0,0 +1,13 @@ | |||
.git/ | |||
.github/ | |||
bin/ | |||
obj/ | |||
.vs/ | |||
.nuget/ | |||
*.csproj.user | |||
*.wapproj.user | |||
wix.exe | |||
wix.exe.config | |||
wix.pdb | |||
*.mp4 | |||
*.png |
@@ -0,0 +1,36 @@ | |||
# THUploadOss | |||
#### Description | |||
{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**} | |||
#### Software Architecture | |||
Software architecture description | |||
#### Installation | |||
1. xxxx | |||
2. xxxx | |||
3. xxxx | |||
#### Instructions | |||
1. xxxx | |||
2. xxxx | |||
3. xxxx | |||
#### Contribution | |||
1. Fork the repository | |||
2. Create Feat_xxx branch | |||
3. Commit your code | |||
4. Create Pull Request | |||
#### Gitee Feature | |||
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md | |||
2. Gitee blog [blog.gitee.com](https://blog.gitee.com) | |||
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore) | |||
4. The most valuable open source project [GVP](https://gitee.com/gvp) | |||
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help) | |||
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) |
@@ -1,3 +1,39 @@ | |||
# THupload-Oss | |||
# THUploadOss | |||
THupload-Oss | |||
#### 介绍 | |||
{**以下是 Gitee 平台说明,您可以替换此简介** | |||
Gitee 是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN)。专为开发者提供稳定、高效、安全的云端软件开发协作平台 | |||
无论是个人、团队、或是企业,都能够用 Gitee 实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)} | |||
#### 软件架构 | |||
软件架构说明 | |||
#### 安装教程 | |||
1. xxxx | |||
2. xxxx | |||
3. xxxx | |||
#### 使用说明 | |||
1. xxxx | |||
2. xxxx | |||
3. xxxx | |||
#### 参与贡献 | |||
1. Fork 本仓库 | |||
2. 新建 Feat_xxx 分支 | |||
3. 提交代码 | |||
4. 新建 Pull Request | |||
#### 特技 | |||
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md | |||
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com) | |||
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目 | |||
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目 | |||
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) | |||
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) |
@@ -0,0 +1,25 @@ | |||
| |||
Microsoft Visual Studio Solution File, Format Version 12.00 | |||
# Visual Studio Version 17 | |||
VisualStudioVersion = 17.4.33403.182 | |||
MinimumVisualStudioVersion = 10.0.40219.1 | |||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "THUploadOss", "THUploadOss\THUploadOss.csproj", "{62FDE986-F39F-486A-85FE-B0E27AB23D25}" | |||
EndProject | |||
Global | |||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | |||
Debug|Any CPU = Debug|Any CPU | |||
Release|Any CPU = Release|Any CPU | |||
EndGlobalSection | |||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | |||
{62FDE986-F39F-486A-85FE-B0E27AB23D25}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
{62FDE986-F39F-486A-85FE-B0E27AB23D25}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{62FDE986-F39F-486A-85FE-B0E27AB23D25}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
{62FDE986-F39F-486A-85FE-B0E27AB23D25}.Release|Any CPU.Build.0 = Release|Any CPU | |||
EndGlobalSection | |||
GlobalSection(SolutionProperties) = preSolution | |||
HideSolutionNode = FALSE | |||
EndGlobalSection | |||
GlobalSection(ExtensibilityGlobals) = postSolution | |||
SolutionGuid = {39711E6D-EA0B-4A80-A16C-94864E655A3F} | |||
EndGlobalSection | |||
EndGlobal |
@@ -0,0 +1,6 @@ | |||
<?xml version="1.0" encoding="utf-8" ?> | |||
<configuration> | |||
<startup> | |||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" /> | |||
</startup> | |||
</configuration> |
@@ -0,0 +1,41 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
namespace THUploadOss | |||
{ | |||
internal class Logger | |||
{ | |||
private static readonly log4net.ILog loginfo = log4net.LogManager.GetLogger("loginfo"); | |||
private static readonly log4net.ILog logerror = log4net.LogManager.GetLogger("logerror"); | |||
public static void WriteInfo(string info) | |||
{ | |||
Console.WriteLine(info); | |||
if (loginfo.IsInfoEnabled) | |||
{ | |||
loginfo.Info(info); | |||
} | |||
} | |||
public static void WriteError(string error) | |||
{ | |||
Console.WriteLine(error); | |||
if (logerror.IsErrorEnabled) | |||
{ | |||
logerror.Error(error); | |||
} | |||
} | |||
public static void WriteError(string info, Exception ex) | |||
{ | |||
Console.WriteLine(info); | |||
if (logerror.IsErrorEnabled) | |||
{ | |||
logerror.Error(info, ex); | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,174 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.IO; | |||
using log4net; | |||
using System.Linq; | |||
using System.Runtime.InteropServices; | |||
using System.Text; | |||
using System.Threading; | |||
using System.Threading.Tasks; | |||
using Aliyun.OSS; | |||
using Newtonsoft.Json; | |||
using uPLibrary.Networking.M2Mqtt; | |||
using uPLibrary.Networking.M2Mqtt.Messages; | |||
using System.Reflection; | |||
using System.Net.NetworkInformation; | |||
using static THUploadOss.Common; | |||
using static System.Net.Mime.MediaTypeNames; | |||
namespace THUploadOss | |||
{ | |||
public partial class Common | |||
{ | |||
public static int StsrtDownload = -1; //注意全局变量要使用static | |||
public static int DownloadFinsh = -1; | |||
public static string ConfigPath = "./config.ini"; | |||
public static string RequestId; | |||
public static int Status = (int)UPLOAD_STATUS.Preparation; | |||
public static double UploadPercent = 0; | |||
public static double DownloadPercent = 0; | |||
public struct FileStates | |||
{ | |||
public string fileName;//文件名 | |||
public string url; | |||
public int status;// 状态:待上传 5 上传中 10 完成 15 失败 20 取消 25 | |||
public string progress; | |||
public string fileType;//pic video | |||
} | |||
public static object lockFileList = new object(); | |||
public static List<FileStates> FileList = new List<FileStates>(); | |||
public enum UPLOAD_STATUS | |||
{ | |||
Preparation = 5, | |||
Uploading = 10, | |||
Complete = 15, | |||
Ccancellation = 20, | |||
Fail = 25 | |||
} | |||
public enum TRMP { | |||
RTMP_OK = 0, | |||
RTMP_START_ACTION_FAIL = 1, | |||
RTMP_STOP_ACTION_FAIL = 2 | |||
} | |||
public static string[] RTMP_RESULT = { "执行成功", | |||
"启动失败,接口调用异常", | |||
"停止失败,接口调用异常 "}; | |||
public enum UPLOAD | |||
{ | |||
UPLOAD_OK = 0, | |||
UPLOAD_START_FAIL = 1, | |||
UPLOAD_STOP_FAIL = 2 | |||
} | |||
public static string[] UPLOAD_RESULT = {"执行成功", | |||
"任务正在执行, 请稍后再试", | |||
"任务停止失败, 任务不存在"}; | |||
[DllImport("kernel32")] | |||
public static extern long GetPrivateProfileString(string section, string key, string defaultValue, StringBuilder retVal, int size, string filePath); | |||
[DllImport("kernel32")] | |||
private static extern long WritePrivateProfileString(string section, string key, string value, string filePath); | |||
[DllImport("kernel32.dll")] | |||
public static extern IntPtr GetConsoleWindow(); | |||
[DllImport("user32.dll")] | |||
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); | |||
} | |||
internal class Program | |||
{ | |||
[DllImport("kernel32.dll")] | |||
static extern IntPtr GetStdHandle(int nStdHandle); | |||
[DllImport("kernel32.dll", SetLastError = true)] | |||
static extern bool SetConsoleTitle(string lpConsoleTitle); | |||
const int STD_INPUT_HANDLE = -10; | |||
const uint ENABLE_QUICK_EDIT_MODE = 0x0040; | |||
[DllImport("kernel32.dll", SetLastError = true)] | |||
internal static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint mode); | |||
[DllImport("kernel32.dll", SetLastError = true)] | |||
internal static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint mode); | |||
public static void THMqttClinetThread() | |||
{ | |||
Logger.WriteInfo("THMqttClinetThread thread starts"); | |||
StringBuilder mqtt = new StringBuilder(50); | |||
GetPrivateProfileString("SWITCH", "mqtt", "配置文件存在,读取未成功!", mqtt, 255, ConfigPath); | |||
if (mqtt.ToString() == "true") | |||
{ | |||
THMqttClinet tHMqttClinet = new THMqttClinet(); | |||
bool ret = tHMqttClinet.InitMqttClient(); | |||
while (ret) | |||
{ | |||
if (tHMqttClinet.mqttClient.IsConnected) | |||
{ | |||
tHMqttClinet.PublishUploadTopic(); | |||
} | |||
else | |||
{ | |||
tHMqttClinet.MqttConnect(); | |||
} | |||
} | |||
} | |||
else { | |||
THHttpServe tHHttpServe = new THHttpServe(); | |||
bool ret = tHHttpServe.InitHttpServer(); | |||
while (ret) | |||
{ | |||
tHHttpServe.UploadStatus(); | |||
} | |||
} | |||
} | |||
public static void THDownloadFileThread() | |||
{ | |||
Logger.WriteInfo("THDownloadFileThread thread starts"); | |||
THDownloadFile tHDownloadFile = new THDownloadFile();//定期删除文件 | |||
bool ret = tHDownloadFile.InitDownloadFile(); | |||
while (ret) | |||
{ | |||
tHDownloadFile.DownloadAllFile(); | |||
} | |||
} | |||
public static void THUploadFileThread() | |||
{ | |||
Logger.WriteInfo("THUploadFileThread thread starts"); | |||
THUploadFile tHUploadFile = new THUploadFile();//断线重传 | |||
tHUploadFile.InitUploadFile(); | |||
while (true) | |||
{ | |||
tHUploadFile.UploadFile(); | |||
} | |||
} | |||
static void Main(string[] args) | |||
{ | |||
//IntPtr handle = GetConsoleWindow(); | |||
//ShowWindow(handle, 0);//隐藏控制台 | |||
IntPtr hStdin = GetStdHandle(STD_INPUT_HANDLE); | |||
uint mode; | |||
GetConsoleMode(hStdin, out mode); | |||
mode &= ~ENABLE_QUICK_EDIT_MODE; | |||
SetConsoleMode(hStdin, mode);//关闭控制台的快速编辑模式 | |||
// 获取标准输出句柄 | |||
Logger.WriteInfo("=====================================STARP================================================="); | |||
IntPtr handle = GetStdHandle(-11); | |||
SetConsoleTitle("MediaTool 1.0.1"); | |||
ThreadStart THMqttClinetchildref = new ThreadStart(THMqttClinetThread); | |||
Thread THMqttClinetChildThread = new Thread(THMqttClinetchildref); | |||
THMqttClinetChildThread.Start(); | |||
ThreadStart THDownloadFilechildref = new ThreadStart(THDownloadFileThread); | |||
Thread THDownloadFileChildThread = new Thread(THDownloadFilechildref); | |||
THDownloadFileChildThread.Start(); | |||
ThreadStart THUploadFilechildref = new ThreadStart(THUploadFileThread); | |||
Thread THUploadFileChildThread = new Thread(THUploadFilechildref); | |||
THUploadFileChildThread.Start(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,37 @@ | |||
using System.Reflection; | |||
using System.Runtime.CompilerServices; | |||
using System.Runtime.InteropServices; | |||
// 有关程序集的一般信息由以下 | |||
// 控制。更改这些特性值可修改 | |||
// 与程序集关联的信息。 | |||
[assembly: AssemblyTitle("THUploadOss")] | |||
[assembly: AssemblyDescription("")] | |||
[assembly: AssemblyConfiguration("")] | |||
[assembly: AssemblyCompany("")] | |||
[assembly: AssemblyProduct("THUploadOss")] | |||
[assembly: AssemblyCopyright("Copyright © 2023")] | |||
[assembly: AssemblyTrademark("")] | |||
[assembly: AssemblyCulture("")] | |||
// 将 ComVisible 设置为 false 会使此程序集中的类型 | |||
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 | |||
//请将此类型的 ComVisible 特性设置为 true。 | |||
[assembly: ComVisible(false)] | |||
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID | |||
[assembly: Guid("62fde986-f39f-486a-85fe-b0e27ab23d25")] | |||
// 程序集的版本信息由下列四个值组成: | |||
// | |||
// 主版本 | |||
// 次版本 | |||
// 生成号 | |||
// 修订号 | |||
// | |||
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 | |||
//通过使用 "*",如下所示: | |||
// [assembly: AssemblyVersion("1.0.*")] | |||
[assembly: AssemblyVersion("1.0.0.0")] | |||
[assembly: AssemblyFileVersion("1.0.0.0")] | |||
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config", ConfigFileExtension = "config", Watch = true)] |
@@ -0,0 +1,63 @@ | |||
//------------------------------------------------------------------------------ | |||
// <auto-generated> | |||
// 此代码由工具生成。 | |||
// 运行时版本:4.0.30319.42000 | |||
// | |||
// 对此文件的更改可能会导致不正确的行为,并且如果 | |||
// 重新生成代码,这些更改将会丢失。 | |||
// </auto-generated> | |||
//------------------------------------------------------------------------------ | |||
namespace THUploadOss.Properties { | |||
using System; | |||
/// <summary> | |||
/// 一个强类型的资源类,用于查找本地化的字符串等。 | |||
/// </summary> | |||
// 此类是由 StronglyTypedResourceBuilder | |||
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 | |||
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen | |||
// (以 /str 作为命令选项),或重新生成 VS 项目。 | |||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] | |||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] | |||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] | |||
internal class Resources { | |||
private static global::System.Resources.ResourceManager resourceMan; | |||
private static global::System.Globalization.CultureInfo resourceCulture; | |||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] | |||
internal Resources() { | |||
} | |||
/// <summary> | |||
/// 返回此类使用的缓存的 ResourceManager 实例。 | |||
/// </summary> | |||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] | |||
internal static global::System.Resources.ResourceManager ResourceManager { | |||
get { | |||
if (object.ReferenceEquals(resourceMan, null)) { | |||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("THUploadOss.Properties.Resources", typeof(Resources).Assembly); | |||
resourceMan = temp; | |||
} | |||
return resourceMan; | |||
} | |||
} | |||
/// <summary> | |||
/// 重写当前线程的 CurrentUICulture 属性,对 | |||
/// 使用此强类型资源类的所有资源查找执行重写。 | |||
/// </summary> | |||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] | |||
internal static global::System.Globalization.CultureInfo Culture { | |||
get { | |||
return resourceCulture; | |||
} | |||
set { | |||
resourceCulture = value; | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,120 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<root> | |||
<!-- | |||
Microsoft ResX Schema | |||
Version 2.0 | |||
The primary goals of this format is to allow a simple XML format | |||
that is mostly human readable. The generation and parsing of the | |||
various data types are done through the TypeConverter classes | |||
associated with the data types. | |||
Example: | |||
... ado.net/XML headers & schema ... | |||
<resheader name="resmimetype">text/microsoft-resx</resheader> | |||
<resheader name="version">2.0</resheader> | |||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> | |||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> | |||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> | |||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> | |||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> | |||
<value>[base64 mime encoded serialized .NET Framework object]</value> | |||
</data> | |||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> | |||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> | |||
<comment>This is a comment</comment> | |||
</data> | |||
There are any number of "resheader" rows that contain simple | |||
name/value pairs. | |||
Each data row contains a name, and value. The row also contains a | |||
type or mimetype. Type corresponds to a .NET class that support | |||
text/value conversion through the TypeConverter architecture. | |||
Classes that don't support this are serialized and stored with the | |||
mimetype set. | |||
The mimetype is used for serialized objects, and tells the | |||
ResXResourceReader how to depersist the object. This is currently not | |||
extensible. For a given mimetype the value must be set accordingly: | |||
Note - application/x-microsoft.net.object.binary.base64 is the format | |||
that the ResXResourceWriter will generate, however the reader can | |||
read any of the formats listed below. | |||
mimetype: application/x-microsoft.net.object.binary.base64 | |||
value : The object must be serialized with | |||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter | |||
: and then encoded with base64 encoding. | |||
mimetype: application/x-microsoft.net.object.soap.base64 | |||
value : The object must be serialized with | |||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter | |||
: and then encoded with base64 encoding. | |||
mimetype: application/x-microsoft.net.object.bytearray.base64 | |||
value : The object must be serialized into a byte array | |||
: using a System.ComponentModel.TypeConverter | |||
: and then encoded with base64 encoding. | |||
--> | |||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> | |||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> | |||
<xsd:element name="root" msdata:IsDataSet="true"> | |||
<xsd:complexType> | |||
<xsd:choice maxOccurs="unbounded"> | |||
<xsd:element name="metadata"> | |||
<xsd:complexType> | |||
<xsd:sequence> | |||
<xsd:element name="value" type="xsd:string" minOccurs="0" /> | |||
</xsd:sequence> | |||
<xsd:attribute name="name" use="required" type="xsd:string" /> | |||
<xsd:attribute name="type" type="xsd:string" /> | |||
<xsd:attribute name="mimetype" type="xsd:string" /> | |||
<xsd:attribute ref="xml:space" /> | |||
</xsd:complexType> | |||
</xsd:element> | |||
<xsd:element name="assembly"> | |||
<xsd:complexType> | |||
<xsd:attribute name="alias" type="xsd:string" /> | |||
<xsd:attribute name="name" type="xsd:string" /> | |||
</xsd:complexType> | |||
</xsd:element> | |||
<xsd:element name="data"> | |||
<xsd:complexType> | |||
<xsd:sequence> | |||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> | |||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> | |||
</xsd:sequence> | |||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> | |||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> | |||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> | |||
<xsd:attribute ref="xml:space" /> | |||
</xsd:complexType> | |||
</xsd:element> | |||
<xsd:element name="resheader"> | |||
<xsd:complexType> | |||
<xsd:sequence> | |||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> | |||
</xsd:sequence> | |||
<xsd:attribute name="name" type="xsd:string" use="required" /> | |||
</xsd:complexType> | |||
</xsd:element> | |||
</xsd:choice> | |||
</xsd:complexType> | |||
</xsd:element> | |||
</xsd:schema> | |||
<resheader name="resmimetype"> | |||
<value>text/microsoft-resx</value> | |||
</resheader> | |||
<resheader name="version"> | |||
<value>2.0</value> | |||
</resheader> | |||
<resheader name="reader"> | |||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | |||
</resheader> | |||
<resheader name="writer"> | |||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | |||
</resheader> | |||
</root> |
@@ -0,0 +1,309 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.IO; | |||
using log4net; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using System.Reflection; | |||
using System.Web.UI.WebControls; | |||
using System.IO.Pipes; | |||
using static THUploadOss.Common; | |||
namespace THUploadOss | |||
{ | |||
public class THDownloadFile | |||
{ | |||
//是指定文件夹下的所有文件,同时还要重命名文件夹,根据订阅的消息重命名文件夹???? | |||
private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | |||
public string m_smbPicPath; // SMB服务器上的图片文件路径 | |||
public string m_smbVideoPath; // SMB服务器上的视频文件路径 | |||
public string m_localPicPath; // 本地保存路径 | |||
public string m_localVideoPath; // 本地保存路径 | |||
public int m_deleteTime; // 本地文件保存时间 | |||
public int m_number = 0; | |||
FileStream readFileStream; | |||
FileStream fileStream; | |||
public bool InitDownloadFile() | |||
{ | |||
if (!getMqttConfig()) | |||
return false; | |||
return true; | |||
} | |||
public bool DownloadAllFile() | |||
{ | |||
if (StsrtDownload == 1) | |||
{ | |||
try | |||
{ | |||
if (m_number++ > 10) | |||
{ | |||
Status = (int)UPLOAD_STATUS.Fail; | |||
StsrtDownload = -1; | |||
DownloadFinsh = -1; | |||
m_number = 0; | |||
return false; | |||
} | |||
string[] picFiles = Directory.GetFiles(m_smbPicPath); | |||
long pictotalSize = 0; | |||
long picindex = 0; | |||
foreach (string file in picFiles) | |||
{ | |||
FileInfo fileinfo = new FileInfo(file); | |||
pictotalSize += fileinfo.Length; | |||
} | |||
Logger.WriteInfo($"THDownloadFile - picFiles Total size: {pictotalSize} bytes"); | |||
// 创建任务名称文件夹 | |||
string newFolderPath = Path.Combine(m_localPicPath, RequestId); | |||
Directory.CreateDirectory(newFolderPath); | |||
foreach (string file in picFiles) | |||
{ | |||
if (StsrtDownload == -1) | |||
{ | |||
RemoveAllFile(m_smbPicPath); | |||
RemoveAllFile(m_smbVideoPath); | |||
m_number = 0; | |||
Logger.WriteInfo("THDownloadFile - 等待删除缓存!"); | |||
System.Threading.Thread.Sleep(60000);//删除延时 | |||
Status = (int)UPLOAD_STATUS.Ccancellation; | |||
Logger.WriteInfo("THDownloadFile - 删除缓存完成!"); | |||
return false; | |||
} | |||
string destinationFilePath = Path.Combine(newFolderPath, Path.GetFileName(file)); | |||
readFileStream = new FileStream(file, FileMode.Open, FileAccess.Read); | |||
fileStream = new FileStream(destinationFilePath, FileMode.Create, FileAccess.Write); | |||
byte[] buffer = new byte[10240]; | |||
int count; | |||
Progress<double> prog = new Progress<double>((theV => | |||
{ | |||
DownloadPercent = (double)theV / pictotalSize * 100; | |||
Logger.WriteInfo($@"THDownloadFile - Now the picFiles Progress:{(DownloadPercent>100?100:DownloadPercent)}%"); | |||
})); | |||
while ((count = readFileStream.Read(buffer, 0, 10240)) != 0 && StsrtDownload != -1) | |||
{ | |||
fileStream.Write(buffer, 0, count); | |||
((IProgress<double>)prog).Report((double)picindex * 10240); | |||
picindex++; | |||
} | |||
fileStream.Close(); | |||
readFileStream.Close(); | |||
} | |||
string[] Videofiles = Directory.GetFiles(m_smbVideoPath); | |||
long videototalSize = 0; | |||
long videoindex = 0; | |||
foreach (string file in Videofiles) | |||
{ | |||
FileInfo fileinfo = new FileInfo(file); | |||
videototalSize += fileinfo.Length; | |||
} | |||
Logger.WriteInfo($"THDownloadFile - Videofiles Total size: {videototalSize} bytes"); | |||
// 创建任务名称文件夹 | |||
newFolderPath = Path.Combine(m_localVideoPath, RequestId); | |||
Directory.CreateDirectory(newFolderPath); | |||
foreach (string file in Videofiles) | |||
{ | |||
if (StsrtDownload == -1) | |||
{ | |||
RemoveAllFile(m_smbPicPath); | |||
RemoveAllFile(m_smbVideoPath); | |||
m_number = 0; | |||
Logger.WriteInfo("THDownloadFile - 等待删除缓存!"); | |||
System.Threading.Thread.Sleep(60000);//删除延时 | |||
Status = (int)UPLOAD_STATUS.Ccancellation; | |||
Logger.WriteInfo("THDownloadFile - 删除缓存完成!"); | |||
return false; | |||
} | |||
string destinationFilePath = Path.Combine(newFolderPath, Path.GetFileName(file)); | |||
readFileStream = new FileStream(file, FileMode.Open, FileAccess.Read); | |||
fileStream = new FileStream(destinationFilePath, FileMode.Create, FileAccess.Write); | |||
byte[] buffer = new byte[10240]; | |||
int count; | |||
Progress<double> prog = new Progress<double>((theV => | |||
{ | |||
DownloadPercent = (double)theV / videototalSize * 100; | |||
Logger.WriteInfo($@"THDownloadFile - Now the Videofiles Progress:{(DownloadPercent > 100 ? 100 : DownloadPercent)}%"); | |||
})); | |||
while ((count = readFileStream.Read(buffer, 0, 10240)) != 0 && StsrtDownload != -1) | |||
{ | |||
//System.Threading.Thread.Sleep(100); | |||
fileStream.Write(buffer, 0, count); | |||
((IProgress<double>)prog).Report((double)videoindex * 10240); | |||
videoindex++; | |||
} | |||
fileStream.Close(); | |||
readFileStream.Close(); | |||
} | |||
Logger.WriteInfo("THDownloadFile - 所有文件下载成功!"); | |||
if (RemoveAllFile(m_smbVideoPath) && RemoveAllFile(m_smbPicPath)) | |||
{ | |||
Logger.WriteInfo("THDownloadFile - 等待删除缓存!"); | |||
System.Threading.Thread.Sleep(60000);//删除延时 | |||
if (StsrtDownload == -1) | |||
{ | |||
m_number = 0; | |||
Status = (int)UPLOAD_STATUS.Ccancellation; | |||
return false; | |||
} | |||
DownloadPercent = 100.00; | |||
Status = (int)UPLOAD_STATUS.Uploading; | |||
StsrtDownload = 0; | |||
DownloadFinsh = 1; | |||
m_number = 0; | |||
Logger.WriteInfo("THDownloadFile - 删除缓存完成!"); | |||
return true; | |||
}else | |||
return false; | |||
} | |||
catch (Exception ex) | |||
{ | |||
if(fileStream !=null) | |||
fileStream.Close(); | |||
if(readFileStream!=null) | |||
readFileStream.Close(); | |||
Logger.WriteError("THDownloadFile - DownloadAllFile-发生异常:" + ex.Message); | |||
return false; | |||
} | |||
} | |||
else | |||
{ | |||
System.Threading.Thread.Sleep(1000); | |||
CleanFile(m_localVideoPath); | |||
CleanFile(m_localPicPath); | |||
return false; | |||
} | |||
} | |||
//实现删除指定文件夹下的所有文件 | |||
public bool RemoveAllFile(string path) | |||
{ | |||
try { | |||
string[] files = Directory.GetFiles(path); | |||
// 逐个删除文件 | |||
foreach (string file in files) | |||
{ | |||
File.Delete(file); | |||
Logger.WriteInfo("THDownloadFile - RemoveFile(" + file + ")-操作完成"); | |||
} | |||
Logger.WriteInfo("THDownloadFile - RemoveAllFile(" + path + ")-操作完成"); | |||
return true; | |||
} catch (Exception ex) | |||
{ | |||
Logger.WriteError("THDownloadFile - RemoveAllFile(" + path + ")-发生异常:" + ex.Message); | |||
return false; | |||
} | |||
} | |||
public void CleanFile(string path) | |||
{ | |||
DateTime nowTime = DateTime.Now; | |||
DirectoryInfo root = new DirectoryInfo(path); | |||
if (root.Exists) { | |||
DirectoryInfo[] dics = root.GetDirectories();//获取文件夹 | |||
FileAttributes attr = File.GetAttributes(path); | |||
if (attr == FileAttributes.Directory)//判断是不是文件夹 | |||
{ | |||
foreach (DirectoryInfo file in dics)//遍历文件夹 | |||
{ | |||
TimeSpan t = nowTime - file.CreationTime; //当前时间 减去 文件创建时间 | |||
int day = t.Days; | |||
if (day > m_deleteTime) //保存的时间 ; 单位:天 | |||
{ | |||
Directory.Delete(file.FullName, true); //删除超过时间的文件夹 | |||
} | |||
} | |||
} | |||
} | |||
} | |||
public bool getMqttConfig() | |||
{ | |||
if (System.IO.File.Exists(ConfigPath)) | |||
{ | |||
try | |||
{ | |||
StringBuilder smbPicPath = new StringBuilder(200); | |||
GetPrivateProfileString("SMBPATH", "smbPicPath", "配置文件存在,读取未成功!", smbPicPath, 255, ConfigPath); | |||
m_smbPicPath = smbPicPath.ToString(); | |||
StringBuilder smbVideoPath = new StringBuilder(200); | |||
GetPrivateProfileString("SMBPATH", "smbVideoPath", "配置文件存在,读取未成功!", smbVideoPath, 255, ConfigPath); | |||
m_smbVideoPath = smbVideoPath.ToString(); | |||
StringBuilder localPicPath = new StringBuilder(10); | |||
GetPrivateProfileString("SMBPATH", "localPicPath", "配置文件存在,读取未成功!", localPicPath, 255, ConfigPath); | |||
m_localPicPath = localPicPath.ToString(); | |||
StringBuilder localVideoPath = new StringBuilder(10); | |||
GetPrivateProfileString("SMBPATH", "localVideoPath", "配置文件存在,读取未成功!", localVideoPath, 255, ConfigPath); | |||
m_localVideoPath = localVideoPath.ToString(); | |||
StringBuilder deleteTime = new StringBuilder(10); | |||
GetPrivateProfileString("SMBPATH", "deleteTime", "配置文件存在,读取未成功!", deleteTime, 255, ConfigPath); | |||
m_deleteTime = int.Parse(deleteTime.ToString()); | |||
return true; | |||
} | |||
catch (Exception ex) | |||
{ | |||
Logger.WriteError("THDownloadFile - getMqttConfig" + ex.Message.ToString()); | |||
return false; | |||
} | |||
} | |||
return false; | |||
} | |||
} | |||
} | |||
////在指定路径下新建文件夹,并将这个路径下所有的png后缀文件移动到新建的文件夹中 | |||
//public bool MoveFile(string path, string folderName, string fileType) | |||
//{ | |||
// try { | |||
// // 创建新文件夹 | |||
// string newFolderPath = Path.Combine(path, folderName); | |||
// Directory.CreateDirectory(newFolderPath); | |||
// // 获取指定路径下的所有png后缀文件 | |||
// string[] files = Directory.GetFiles(path, fileType); | |||
// // 遍历所有png文件,将其移动到新建的文件夹中 | |||
// foreach (string file in files) | |||
// { | |||
// string fileName = Path.GetFileName(file); | |||
// string newFilePath = Path.Combine(newFolderPath, fileName); | |||
// File.Move(file, newFilePath); | |||
// } | |||
// Logger.WriteInfo("THDownloadFile - MoveFile(" + path +"," + folderName+","+ fileType + ")-操作完成"); | |||
// return true; | |||
// } catch (Exception ex) | |||
// { | |||
// Logger.WriteError("THDownloadFile - MoveFile(" + path +"," + folderName+","+ fileType + ")-发生异常:" + ex.Message); | |||
// return false; | |||
// } | |||
//} |
@@ -0,0 +1,436 @@ | |||
using log4net; | |||
using Newtonsoft.Json.Linq; | |||
using Newtonsoft.Json; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.IO; | |||
using System.Linq; | |||
using System.Net; | |||
using System.Net.Sockets; | |||
using System.Reflection; | |||
using System.Text; | |||
using System.Threading; | |||
using System.Threading.Tasks; | |||
using System.Web.UI; | |||
using static THUploadOss.Common; | |||
using System.Net.Http; | |||
using System.Runtime.Remoting.Contexts; | |||
using uPLibrary.Networking.M2Mqtt.Messages; | |||
using uPLibrary.Networking.M2Mqtt; | |||
namespace THUploadOss | |||
{ | |||
internal class THHttpServe | |||
{ | |||
public string m_listenerUrl; | |||
private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | |||
public string m_callback; | |||
public HttpListener httpListener; | |||
public bool StartListener() | |||
{ | |||
try | |||
{ | |||
httpListener = new HttpListener(); | |||
httpListener.AuthenticationSchemes = AuthenticationSchemes.Anonymous; | |||
httpListener.Prefixes.Add(m_listenerUrl); | |||
httpListener.Start(); | |||
httpListener.BeginGetContext(ListenerHandle, httpListener); //开始监听 | |||
return true; | |||
} | |||
catch (Exception e) | |||
{ | |||
Logger.WriteError("THHttpServe: StartListener-ERROR:" + $"服务器启动失败!{e.Message}"); | |||
return false; | |||
} | |||
} | |||
public void ListenerHandle(IAsyncResult result) | |||
{ | |||
try | |||
{ | |||
httpListener = result.AsyncState as HttpListener; | |||
if (httpListener == null) return; | |||
if (httpListener.IsListening) | |||
{ | |||
httpListener.BeginGetContext(ListenerHandle, httpListener); //继续监听 | |||
HttpListenerContext context = httpListener.EndGetContext(result); | |||
HttpListenerRequest request = context.Request; | |||
Stream stream = context.Request.InputStream; | |||
StreamReader reader = new StreamReader(stream, Encoding.UTF8); | |||
string content = reader.ReadToEnd(); | |||
Logger.WriteInfo("THHttpServe: ListenerHandle()-收到消息:" + content); | |||
switch (request.RawUrl) | |||
{ | |||
case "/upload/start": | |||
{ | |||
dynamic jsonObj = JsonConvert.DeserializeObject(content); | |||
if (StsrtDownload != -1) | |||
{ | |||
UploadResponse(context, (int)UPLOAD.UPLOAD_START_FAIL); | |||
return; | |||
} | |||
lock (lockFileList) | |||
{ | |||
for (int i = FileList.Count - 1; i >= 0; i--) | |||
{ | |||
FileList.Remove(FileList[i]); | |||
} | |||
} | |||
RequestId = jsonObj.requestId; | |||
m_callback = jsonObj.callbackUrl; | |||
DownloadFinsh = 0; | |||
StsrtDownload = 1; | |||
Status = (int)UPLOAD_STATUS.Preparation; | |||
UploadResponse(context, (int)UPLOAD.UPLOAD_OK); | |||
} | |||
break; | |||
case "/upload/stop": | |||
{ | |||
if (StsrtDownload == -1) | |||
{ | |||
UploadResponse(context,(int)UPLOAD.UPLOAD_STOP_FAIL); | |||
return; | |||
} | |||
DownloadFinsh = -1; | |||
StsrtDownload = -1; | |||
//Status = (int)UPLOAD_STATUS.Ccancellation; | |||
UploadResponse(context, (int)UPLOAD.UPLOAD_OK); | |||
} | |||
break; | |||
case "/upload/callback": | |||
{ | |||
UploadStatusResponse(context); | |||
} | |||
break; | |||
} | |||
} | |||
} | |||
catch (Exception ex) | |||
{ | |||
Logger.WriteError("THHttpServe: ListenerHandle" + $"异常:{ex.StackTrace}"); | |||
} | |||
} | |||
public void UploadStatus() | |||
{ | |||
Logger.WriteError("Http UploadStatus: StsrtDownload:" + StsrtDownload + "Status:" + Status); | |||
if (StsrtDownload != -1 || Status != (int)UPLOAD_STATUS.Preparation) | |||
{ | |||
JObject data = new JObject | |||
{ | |||
{ "requestId", RequestId }, | |||
{ "errorCode", "" }, | |||
{ "errorMsg", "" }, | |||
{ "status", Status },// 状态:待执行 5 执行中 10 完成 15 超时 20 失败 25 | |||
{ "currentTime", DateTime.Now.ToString() } | |||
}; | |||
JArray imgjArray = new JArray(); | |||
JArray videojArray = new JArray(); | |||
lock (lockFileList) | |||
{ | |||
foreach (FileStates file in FileList) | |||
{ | |||
if (file.fileType == "pic") | |||
{ | |||
JObject img = new JObject | |||
{ | |||
{ "fileName", file.fileName}, | |||
{ "imageUrl",file.url }, | |||
{ "status",file.status }, | |||
{ "progress",file.progress} | |||
}; | |||
imgjArray.Add(img); | |||
} | |||
if (file.fileType == "video") | |||
{ | |||
JObject video = new JObject | |||
{ | |||
{ "fileName", file.fileName}, | |||
{ "videoUrl",file.url }, | |||
{ "status",file.status }, | |||
{ "progress",file.progress } | |||
}; | |||
videojArray.Add(video); | |||
} | |||
} | |||
} | |||
data.Add("imageList", new JArray(imgjArray)); | |||
data.Add("videoList", new JArray(videojArray)); | |||
// 将对象序列化为 JSON 字符串 | |||
string json = JsonConvert.SerializeObject(data); | |||
Logger.WriteInfo("THHttpServe: UploadStatus-交互日志:" + json); | |||
try | |||
{ | |||
HttpClient client = new HttpClient(); | |||
HttpContent content = new StringContent(json, Encoding.UTF8, "application/json"); | |||
HttpResponseMessage response = client.PostAsync(m_callback, content).Result; | |||
// 检查响应状态码 | |||
if (response.IsSuccessStatusCode) | |||
{ | |||
string responseBody = response.Content.ReadAsStringAsync().Result; | |||
} | |||
else | |||
{ | |||
Logger.WriteError("THHttpServe: UploadStatus-Error sending GET request: " + response.StatusCode); | |||
} | |||
} | |||
catch (Exception ex) | |||
{ | |||
Logger.WriteError("THHttpServe: UploadStatus-An error occurred: " + ex.Message); | |||
} | |||
if (Status == (int)UPLOAD_STATUS.Complete) | |||
Status = (int)UPLOAD_STATUS.Preparation; | |||
if (Status == (int)UPLOAD_STATUS.Fail) | |||
Status = (int)UPLOAD_STATUS.Preparation; | |||
if (Status == (int)UPLOAD_STATUS.Ccancellation) | |||
Status = (int)UPLOAD_STATUS.Preparation; | |||
} | |||
System.Threading.Thread.Sleep(5000); | |||
} | |||
public void UploadStatusResponse(HttpListenerContext context) | |||
{ | |||
//构造Response响应 | |||
HttpListenerResponse response = context.Response; | |||
response.StatusCode = 200; | |||
response.ContentType = "text/html;"; | |||
response.ContentEncoding = Encoding.UTF8; | |||
using (StreamWriter writer = new StreamWriter(response.OutputStream, Encoding.UTF8)) | |||
{ | |||
JObject data = new JObject | |||
{ | |||
{ "requestId", RequestId }, | |||
{ "errorCode", "" }, | |||
{ "errorMsg", "" }, | |||
{ "status", Status },// 状态:待执行 5 执行中 10 完成 15 超时 20 失败 25 | |||
{ "currentTime", DateTime.Now.ToString() } | |||
}; | |||
JArray imgjArray = new JArray(); | |||
JArray videojArray = new JArray(); | |||
lock (lockFileList) | |||
{ | |||
foreach (FileStates file in FileList) | |||
{ | |||
if (file.fileType == "pic") | |||
{ | |||
JObject img = new JObject | |||
{ | |||
{ "fileName", file.fileName}, | |||
{ "imageUrl",file.url }, | |||
{ "status",file.status }, | |||
{ "progress",file.progress} | |||
}; | |||
imgjArray.Add(img); | |||
} | |||
if (file.fileType == "video") | |||
{ | |||
JObject video = new JObject | |||
{ | |||
{ "fileName", file.fileName}, | |||
{ "videoUrl",file.url }, | |||
{ "status",file.status }, | |||
{ "progress",file.progress } | |||
}; | |||
videojArray.Add(video); | |||
} | |||
} | |||
} | |||
data.Add("imageList", new JArray(imgjArray)); | |||
data.Add("videoList", new JArray(videojArray)); | |||
// 将对象序列化为 JSON 字符串 | |||
string json = JsonConvert.SerializeObject(data); | |||
Logger.WriteInfo("THHttpServe: UploadStatusResponse-交互日志:" + json); | |||
writer.Write(json); | |||
writer.Close(); | |||
response.Close(); | |||
} | |||
} | |||
public void RtmpResponse(HttpListenerContext context, int code) | |||
{ | |||
//构造Response响应 | |||
HttpListenerResponse response = context.Response; | |||
response.StatusCode = 200; | |||
response.ContentType = "text/html;"; | |||
response.ContentEncoding = Encoding.UTF8; | |||
using (StreamWriter writer = new StreamWriter(response.OutputStream, Encoding.UTF8)) | |||
{ | |||
string jsonret = $"{{\"code\":{code},\"msg\":\"{UPLOAD_RESULT[code]}\",\"data\":\"{null}\",\"class\":\"{null}\"}}"; | |||
Logger.WriteInfo("THHttpServe: RtmpResponse-交互日志:" + jsonret); | |||
writer.Write(jsonret); | |||
writer.Close(); | |||
response.Close(); | |||
} | |||
} | |||
public void UploadResponse(HttpListenerContext context,int code) | |||
{ | |||
//构造Response响应 | |||
HttpListenerResponse response = context.Response; | |||
response.StatusCode = 200; | |||
response.ContentType = "text/html;"; | |||
response.ContentEncoding = Encoding.UTF8; | |||
using (StreamWriter writer = new StreamWriter(response.OutputStream, Encoding.UTF8)) | |||
{ | |||
string jsonret = $"{{\"code\":{code},\"msg\":\"{UPLOAD_RESULT[code]}\",\"data\":\"{null}\",\"class\":\"{null}\"}}"; | |||
Logger.WriteInfo("THHttpServe: UploadResponse-交互日志:" + jsonret); | |||
writer.Write(jsonret); | |||
writer.Close(); | |||
response.Close(); | |||
} | |||
} | |||
public bool CloseRtmpChannel() | |||
{ | |||
// 创建HttpClient实例 | |||
HttpClient client = new HttpClient(); | |||
try | |||
{ | |||
// 发送GET请求并获取响应 | |||
HttpResponseMessage response = client.GetAsync("http://localhost:19610/api/v1/getChannelList?offset=0&row=50").Result; | |||
// 检查响应是否成功 | |||
if (response.IsSuccessStatusCode) | |||
{ | |||
// 读取响应内容 | |||
string content = response.Content.ReadAsStringAsync().Result; | |||
Logger.WriteInfo("CloseRtmpChannel" + content); | |||
dynamic jsonObj = JsonConvert.DeserializeObject(content); | |||
string srcURL = jsonObj.ChannelList[0].srcURL; | |||
srcURL = WebUtility.UrlEncode(srcURL).Replace("%3A", ":"); | |||
string dstURL = jsonObj.ChannelList[0].dstURL; | |||
dstURL = WebUtility.UrlEncode(dstURL).Replace("%3A", ":"); | |||
string closeUrl = "http://127.0.0.1:19610/api/v1/updateChannel?indexCode=" + jsonObj.ChannelList[0].indexcode + "&name=" + jsonObj.ChannelList[0].name + "&srcURL=%22" + srcURL + "%22&connectType=" + jsonObj.ChannelList[0].connectType + "&timeout=" + jsonObj.ChannelList[0].connectTimeout + "&mediaType=video" + "&dstURL=" + dstURL + "&dstFormat=rtmp&enable=false"; | |||
// 输出响应内容 | |||
HttpResponseMessage closeResponse = client.GetAsync(closeUrl).Result; | |||
if (closeResponse.IsSuccessStatusCode) | |||
{ | |||
string closeContent = closeResponse.Content.ReadAsStringAsync().Result; | |||
Logger.WriteInfo("CloseRtmpChannel" + closeContent); | |||
if (closeContent == "OK") | |||
return true; | |||
else | |||
return false; | |||
} | |||
} | |||
else | |||
{ | |||
Logger.WriteError("THHttpServe: CloseRtmpChannel-请求失败,状态码:" + response.StatusCode); | |||
return false; | |||
} | |||
} | |||
catch (Exception e) | |||
{ | |||
Logger.WriteError($"THHttpServe: CloseRtmpChannel-其他错误发生: {e.Message}"); | |||
return false; | |||
} | |||
return false; | |||
} | |||
public bool OpenRtmpChannel() | |||
{ | |||
// 创建HttpClient实例 | |||
HttpClient client = new HttpClient(); | |||
try | |||
{ | |||
// 发送GET请求并获取响应 | |||
HttpResponseMessage response = client.GetAsync("http://localhost:19610/api/v1/getChannelList?offset=0&row=50").Result; | |||
// 检查响应是否成功 | |||
if (response.IsSuccessStatusCode) | |||
{ | |||
// 读取响应内容 | |||
string content = response.Content.ReadAsStringAsync().Result; | |||
// 输出响应内容 | |||
Logger.WriteInfo("OpenRtmpChannel: "+content); | |||
dynamic jsonObj = JsonConvert.DeserializeObject(content); | |||
string srcURL = jsonObj.ChannelList[0].srcURL; | |||
srcURL = WebUtility.UrlEncode(srcURL).Replace("%3A", ":"); | |||
string dstURL = jsonObj.ChannelList[0].dstURL; | |||
dstURL = WebUtility.UrlEncode(dstURL).Replace("%3A", ":"); | |||
string openUrl = "http://127.0.0.1:19610/api/v1/updateChannel?indexCode=" + jsonObj.ChannelList[0].indexcode + "&name=" + jsonObj.ChannelList[0].name + "&srcURL=%22" + srcURL + "%22&connectType=" + jsonObj.ChannelList[0].connectType + "&timeout=" + jsonObj.ChannelList[0].connectTimeout + "&mediaType=video" + "&dstURL=" + dstURL + "&dstFormat=rtmp&enable=true"; | |||
// 输出响应内容 | |||
HttpResponseMessage openResponse = client.GetAsync(openUrl).Result; | |||
if (openResponse.IsSuccessStatusCode) | |||
{ | |||
string closeContent = openResponse.Content.ReadAsStringAsync().Result; | |||
Logger.WriteInfo("OpenRtmpChannel: "+closeContent); | |||
if (closeContent == "OK") | |||
return true; | |||
else | |||
return false; | |||
} | |||
} | |||
else | |||
{ | |||
Logger.WriteError("THHttpServe: OpenRtmpChannel-请求失败,状态码:" + response.StatusCode); | |||
return false; | |||
} | |||
} | |||
catch (Exception e) | |||
{ | |||
Logger.WriteError($"THHttpServe: OpenRtmpChannel-其他错误发生: {e.Message}"); | |||
return false; | |||
} | |||
return false; | |||
} | |||
//停止HTTP请求监听 | |||
private void StopListener() | |||
{ | |||
if (httpListener != null) | |||
{ | |||
httpListener.Close(); | |||
Logger.WriteError("THHttpServe: StopListener-ERROR:" + "停止数据监听"); | |||
} | |||
} | |||
public bool InitHttpServer() | |||
{ | |||
if (!getMqttConfig()) | |||
return false; | |||
if(!StartListener()) | |||
return false; | |||
return true; | |||
} | |||
public bool getMqttConfig() | |||
{ | |||
if (System.IO.File.Exists(ConfigPath)) | |||
{ | |||
try | |||
{ | |||
StringBuilder listenerUrl = new StringBuilder(20); | |||
GetPrivateProfileString("HTTP", "listenerUrl", "配置文件存在,读取未成功!", listenerUrl, 255, ConfigPath); | |||
m_listenerUrl = listenerUrl.ToString(); | |||
return true; | |||
} | |||
catch (Exception ex) | |||
{ | |||
Logger.WriteError("THHttpServe: getMqttConfig" + ex.Message.ToString()); | |||
return false; | |||
} | |||
} | |||
return false; | |||
} | |||
} | |||
} | |||
//case "/easy/rtmp/start": | |||
// { | |||
// if(OpenRtmpChannel()) | |||
// RtmpResponse(context, (int)TRMP.RTMP_OK); | |||
// else | |||
// RtmpResponse(context, (int)TRMP.RTMP_START_ACTION_FAIL); | |||
// } | |||
// break; | |||
//case "/easy/rtmp/stop": | |||
// { | |||
// if(CloseRtmpChannel()) | |||
// RtmpResponse(context, (int)TRMP.RTMP_OK); | |||
// else | |||
// RtmpResponse(context, (int)TRMP.RTMP_STOP_ACTION_FAIL); | |||
// } | |||
// break; |
@@ -0,0 +1,372 @@ | |||
using Newtonsoft.Json; | |||
using System; | |||
using log4net; | |||
using log4net.Config; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using uPLibrary.Networking.M2Mqtt.Messages; | |||
using uPLibrary.Networking.M2Mqtt; | |||
using System.Runtime.InteropServices; | |||
using System.Reflection; | |||
using System.Net.Http; | |||
using System.Web.UI.WebControls; | |||
using System.Threading; | |||
using static THUploadOss.Common; | |||
using System.Net; | |||
using System.IO; | |||
using Newtonsoft.Json.Linq; | |||
namespace THUploadOss | |||
{ | |||
public class THMqttClinet | |||
{ | |||
public MqttClient mqttClient; | |||
public string m_brokerAddress; // MQTT Broker的地址 106.15.120.154 "192.168.253.130" | |||
public int m_brokerPort; // MQTT Broker的端口号 | |||
public string m_clientId; // 客户端的ID,机场编号 | |||
public string m_airportCode; // 控制编号 | |||
public string m_username; // MQTT Broker的用户名 | |||
public string m_password; // MQTT Broker的密码 | |||
public string m_uploadSubTopic; // 文件上传订阅 topic | |||
public string m_uploadResTopic; // 文件上传响应 topic | |||
public string m_rtmpSubTic; // rtmp订阅 topic | |||
public string m_rtmpResTopic; // rtmp响应 topic | |||
private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | |||
public void MqttClient_MqttMsgPublished(object sender, MqttMsgPublishedEventArgs e) | |||
{ | |||
//Console.WriteLine("[" + DateTime.Now.ToString() + "]" + "消息已发布!"); | |||
//log.Info("[" + DateTime.Now.ToString() + "]" + "主题:" + msg.Topic + " 收到消息:" + jsonObj.command + " " + jsonObj.requestId); | |||
//发布时会触发:用来记录发布的日志?????????????????????? | |||
} | |||
public void MqttClient_MqttMsgReceived(object sender, MqttMsgPublishEventArgs msg) | |||
{ | |||
string message = Encoding.UTF8.GetString(msg.Message); | |||
dynamic jsonObj = JsonConvert.DeserializeObject(message); | |||
Logger.WriteInfo("THMqttClinet: MqttClient_MqttMsgReceived-主题:" + msg.Topic + " 收到消息:" + message); | |||
if (msg.Topic == m_uploadSubTopic && jsonObj.command == "start" )//有任务正在执行中,则不能执行此操作需要返回???????????????? | |||
{ | |||
if (StsrtDownload != -1) | |||
{ | |||
Logger.WriteInfo("THMqttClinet: 有任务正在进行中,MqttClient_MqttMsgReceived-主题:" + msg.Topic + " 收到消息:" + message); | |||
return; | |||
} | |||
RequestId = jsonObj.requestId; | |||
DownloadFinsh = 0; | |||
StsrtDownload = 1; | |||
Status = (int)UPLOAD_STATUS.Preparation; | |||
lock (lockFileList) | |||
{ | |||
for (int i = FileList.Count - 1; i >= 0; i--) | |||
{ | |||
FileList.Remove(FileList[i]); | |||
} | |||
} | |||
} | |||
if (msg.Topic == m_uploadSubTopic && jsonObj.command == "stop") | |||
{ | |||
DownloadFinsh = -1; | |||
StsrtDownload = -1; | |||
//Status = (int)UPLOAD_STATUS.Ccancellation; | |||
} | |||
if (msg.Topic == m_rtmpSubTic && jsonObj.command == "start") | |||
{ | |||
if (OpenRtmpChannel()) | |||
PublishRtmpTopic((int)TRMP.RTMP_OK); | |||
else | |||
PublishRtmpTopic((int)TRMP.RTMP_START_ACTION_FAIL); | |||
} | |||
if (msg.Topic == m_rtmpSubTic && jsonObj.command == "stop") | |||
{ | |||
if (CloseRtmpChannel()) | |||
PublishRtmpTopic((int)TRMP.RTMP_OK); | |||
else | |||
PublishRtmpTopic((int)TRMP.RTMP_STOP_ACTION_FAIL); | |||
} | |||
} | |||
public bool InitMqttClient() | |||
{ | |||
if (!getMqttConfig()) | |||
return false; | |||
try | |||
{ | |||
mqttClient = new MqttClient(m_brokerAddress, m_brokerPort, false, null, null, MqttSslProtocols.None); | |||
mqttClient.MqttMsgPublished += MqttClient_MqttMsgPublished; | |||
mqttClient.MqttMsgPublishReceived += MqttClient_MqttMsgReceived; | |||
if(MqttConnect()) | |||
return true; | |||
else | |||
return false; | |||
} | |||
catch (Exception ex) | |||
{ | |||
Logger.WriteError("THMqttClinet: InitMqttClient-MQTT发生错误:" + ex.Message.ToString()); | |||
System.Threading.Thread.Sleep(1000); | |||
return false; | |||
} | |||
} | |||
public bool MqttConnect() | |||
{ | |||
try | |||
{ | |||
mqttClient.Connect(m_clientId, m_username, m_password); | |||
System.Threading.Thread.Sleep(2000); | |||
if (mqttClient.IsConnected) | |||
{ | |||
mqttClient.Subscribe(new string[] { m_uploadSubTopic }, new byte[] { MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE }); | |||
mqttClient.Subscribe(new string[] { m_rtmpSubTic }, new byte[] { MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE }); | |||
Logger.WriteInfo("THMqttClinet: MqttConnect-连接到MQTT Broker"); | |||
return true; | |||
} | |||
else | |||
{ | |||
Logger.WriteError("THMqttClinet: MqttConnect-无法连接到MQTT Broker!"); | |||
System.Threading.Thread.Sleep(1000); | |||
return false; | |||
} | |||
} | |||
catch (Exception ex) | |||
{ | |||
Logger.WriteError("THMqttClinet: MqttConnect-MQTT发生错误:" + ex.Message); | |||
System.Threading.Thread.Sleep(1000); | |||
return false; | |||
} | |||
} | |||
public int PublishUploadTopic() | |||
{ | |||
Logger.WriteError("MQTT PublishUploadTopic: StsrtDownload:" + StsrtDownload + "Status:"+ Status); | |||
if (StsrtDownload != -1 || Status != (int)UPLOAD_STATUS.Preparation) | |||
{ | |||
JObject data = new JObject | |||
{ | |||
{ "requestId", RequestId }, | |||
{ "errorCode", "" }, | |||
{ "errorMsg", "" }, | |||
{ "status", Status },// 状态:待执行 5 执行中 10 完成 15 超时 20 失败 25 | |||
{ "currentTime", DateTime.Now.ToString() } | |||
}; | |||
JArray imgjArray = new JArray(); | |||
JArray videojArray = new JArray(); | |||
lock (lockFileList) | |||
{ | |||
foreach (FileStates file in FileList) | |||
{ | |||
if (file.fileType == "pic") | |||
{ | |||
JObject img = new JObject | |||
{ | |||
{ "fileName", file.fileName}, | |||
{ "imageUrl",file.url }, | |||
{ "status",file.status }, | |||
{ "progress",file.progress} | |||
}; | |||
imgjArray.Add(img); | |||
} | |||
if (file.fileType == "video") | |||
{ | |||
JObject video = new JObject | |||
{ | |||
{ "fileName", file.fileName}, | |||
{ "videoUrl",file.url }, | |||
{ "status",file.status }, | |||
{ "progress",file.progress } | |||
}; | |||
videojArray.Add(video); | |||
} | |||
} | |||
} | |||
data.Add("imageList", new JArray(imgjArray)); | |||
data.Add("videoList", new JArray(videojArray)); | |||
// 将对象序列化为 JSON 字符串 | |||
string json = JsonConvert.SerializeObject(data); | |||
Logger.WriteInfo("THMqttClinet: PublishUploadTopic:" + json); | |||
mqttClient.Publish(m_uploadResTopic, Encoding.UTF8.GetBytes(json), MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE, false); | |||
if (Status == (int)UPLOAD_STATUS.Complete) | |||
Status = (int)UPLOAD_STATUS.Preparation; | |||
if (Status == (int)UPLOAD_STATUS.Fail) | |||
Status = (int)UPLOAD_STATUS.Preparation; | |||
if (Status == (int)UPLOAD_STATUS.Ccancellation) | |||
Status = (int)UPLOAD_STATUS.Preparation; | |||
} | |||
System.Threading.Thread.Sleep(5000); | |||
return 0; | |||
} | |||
public int PublishRtmpTopic(int ret) | |||
{ | |||
var data = new { code = ret , msg = RTMP_RESULT[ret], data = "null" }; | |||
string json = JsonConvert.SerializeObject(data); | |||
Logger.WriteInfo("THMqttClinet: PublishRtmpTopic:" + json); | |||
mqttClient.Publish(m_rtmpResTopic, Encoding.UTF8.GetBytes(json), MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE, false); | |||
return 0; | |||
} | |||
public bool CloseRtmpChannel() | |||
{ | |||
// 创建HttpClient实例 | |||
HttpClient client = new HttpClient(); | |||
try | |||
{ | |||
// 发送GET请求并获取响应 | |||
HttpResponseMessage response = client.GetAsync("http://localhost:19610/api/v1/getChannelList?offset=0&row=50").Result; | |||
// 检查响应是否成功 | |||
if (response.IsSuccessStatusCode) | |||
{ | |||
// 读取响应内容 | |||
string content = response.Content.ReadAsStringAsync().Result; | |||
Logger.WriteInfo("CloseRtmpChannel: "+content); | |||
dynamic jsonObj = JsonConvert.DeserializeObject(content); | |||
string srcURL = jsonObj.ChannelList[0].srcURL; | |||
srcURL = WebUtility.UrlEncode(srcURL).Replace("%3A", ":"); | |||
string dstURL = jsonObj.ChannelList[0].dstURL; | |||
dstURL = WebUtility.UrlEncode(dstURL).Replace("%3A", ":"); | |||
string closeUrl = "http://127.0.0.1:19610/api/v1/updateChannel?indexCode=" + jsonObj.ChannelList[0].indexcode + "&name=" + jsonObj.ChannelList[0].name + "&srcURL=%22" + srcURL + "%22&connectType=" + jsonObj.ChannelList[0].connectType + "&timeout=" + jsonObj.ChannelList[0].connectTimeout + "&mediaType=video" + "&dstURL=" + dstURL + "&dstFormat=rtmp&enable=false"; | |||
// 输出响应内容 | |||
HttpResponseMessage closeResponse = client.GetAsync(closeUrl).Result; | |||
if (closeResponse.IsSuccessStatusCode) | |||
{ | |||
string closeContent = closeResponse.Content.ReadAsStringAsync().Result; | |||
Logger.WriteInfo("CloseRtmpChannel: "+closeContent); | |||
if (closeContent == "OK") | |||
return true; | |||
else | |||
return false; | |||
} | |||
} | |||
else | |||
{ | |||
Logger.WriteError("THMqttClinet: CloseRtmpChannel-请求失败,状态码:" + response.StatusCode); | |||
return false; | |||
} | |||
} | |||
catch (Exception e) | |||
{ | |||
Logger.WriteError($"THMqttClinet: CloseRtmpChannel-其他错误发生: {e.Message}"); | |||
return false; | |||
} | |||
return false; | |||
} | |||
public bool OpenRtmpChannel() | |||
{ | |||
// 创建HttpClient实例 | |||
HttpClient client = new HttpClient(); | |||
try | |||
{ | |||
// 发送GET请求并获取响应 | |||
HttpResponseMessage response = client.GetAsync("http://localhost:19610/api/v1/getChannelList?offset=0&row=50").Result; | |||
// 检查响应是否成功 | |||
if (response.IsSuccessStatusCode) | |||
{ | |||
// 读取响应内容 | |||
string content = response.Content.ReadAsStringAsync().Result; | |||
// 输出响应内容 | |||
Logger.WriteInfo("OpenRtmpChannel: "+content); | |||
dynamic jsonObj = JsonConvert.DeserializeObject(content); | |||
string srcURL = jsonObj.ChannelList[0].srcURL; | |||
srcURL = WebUtility.UrlEncode(srcURL).Replace("%3A", ":"); | |||
string dstURL = jsonObj.ChannelList[0].dstURL; | |||
dstURL = WebUtility.UrlEncode(dstURL).Replace("%3A", ":"); | |||
string openUrl = "http://127.0.0.1:19610/api/v1/updateChannel?indexCode=" + jsonObj.ChannelList[0].indexcode + "&name=" + jsonObj.ChannelList[0].name + "&srcURL=%22" + srcURL + "%22&connectType=" + jsonObj.ChannelList[0].connectType + "&timeout=" + jsonObj.ChannelList[0].connectTimeout + "&mediaType=video" + "&dstURL=" + dstURL + "&dstFormat=rtmp&enable=true"; | |||
// 输出响应内容 | |||
HttpResponseMessage openResponse = client.GetAsync(openUrl).Result; | |||
if (openResponse.IsSuccessStatusCode) | |||
{ | |||
string closeContent = openResponse.Content.ReadAsStringAsync().Result; | |||
Logger.WriteInfo("OpenRtmpChannel: "+closeContent); | |||
if (closeContent == "OK") | |||
return true; | |||
else | |||
return false; | |||
} | |||
} | |||
else | |||
{ | |||
Logger.WriteError("THMqttClinet: OpenRtmpChannel-请求失败,状态码:" + response.StatusCode); | |||
return false; | |||
} | |||
} | |||
catch (Exception e) | |||
{ | |||
Logger.WriteError($"THMqttClinet: OpenRtmpChannel-其他错误发生: {e.Message}"); | |||
return false; | |||
} | |||
return false; | |||
} | |||
public bool getMqttConfig() | |||
{ | |||
if (System.IO.File.Exists(ConfigPath)) | |||
{ | |||
try { | |||
StringBuilder brokerAddress = new StringBuilder(20); | |||
GetPrivateProfileString("MQTT", "brokerAddress", "配置文件存在,读取未成功!", brokerAddress, 255, ConfigPath); | |||
m_brokerAddress = brokerAddress.ToString(); | |||
StringBuilder brokerPort = new StringBuilder(20); | |||
GetPrivateProfileString("MQTT", "brokerPort", "配置文件存在,读取未成功!", brokerPort, 255, ConfigPath); | |||
m_brokerPort = int.Parse(brokerPort.ToString()); | |||
StringBuilder airportCode = new StringBuilder(100); | |||
GetPrivateProfileString("MQTT", "airportCode", "配置文件存在,读取未成功!", airportCode, 255, ConfigPath); | |||
m_airportCode = airportCode.ToString(); | |||
StringBuilder clientId = new StringBuilder(100); | |||
GetPrivateProfileString("MQTT", "clientId", "配置文件存在,读取未成功!", clientId, 255, ConfigPath); | |||
m_clientId = clientId.ToString(); | |||
StringBuilder username = new StringBuilder(100); | |||
GetPrivateProfileString("MQTT", "username", "配置文件存在,读取未成功!", username, 255, ConfigPath); | |||
m_username = username.ToString(); | |||
StringBuilder password = new StringBuilder(100); | |||
GetPrivateProfileString("MQTT", "password", "配置文件存在,读取未成功!", password, 255, ConfigPath); | |||
m_password = password.ToString(); | |||
StringBuilder uploadSubTopic = new StringBuilder(100); | |||
GetPrivateProfileString("MQTT", "uploadSubTopic", "配置文件存在,读取未成功!", uploadSubTopic, 255, ConfigPath); | |||
m_uploadSubTopic = uploadSubTopic.ToString(); | |||
m_uploadSubTopic = m_uploadSubTopic.Replace("&", m_airportCode); | |||
StringBuilder uploadResTopic = new StringBuilder(100); | |||
GetPrivateProfileString("MQTT", "uploadResTopic", "配置文件存在,读取未成功!", uploadResTopic, 255, ConfigPath); | |||
m_uploadResTopic = uploadResTopic.ToString(); | |||
m_uploadResTopic = m_uploadResTopic.Replace("&", m_airportCode); | |||
StringBuilder rtmpSubTic = new StringBuilder(100); | |||
GetPrivateProfileString("MQTT", "rtmpSubTic", "配置文件存在,读取未成功!", rtmpSubTic, 255, ConfigPath); | |||
m_rtmpSubTic = rtmpSubTic.ToString(); | |||
m_rtmpSubTic = m_rtmpSubTic.Replace("&", m_airportCode); | |||
StringBuilder rtmpResTopic = new StringBuilder(100); | |||
GetPrivateProfileString("MQTT", "rtmpResTopic", "配置文件存在,读取未成功!", rtmpResTopic, 255, ConfigPath); | |||
m_rtmpResTopic = rtmpResTopic.ToString(); | |||
m_rtmpResTopic = m_rtmpResTopic.Replace("&", m_airportCode); | |||
return true; | |||
} | |||
catch (Exception ex) | |||
{ | |||
Logger.WriteError("THMqttClinet: getMqttConfig" + ex.Message.ToString()); | |||
return false; | |||
} | |||
} | |||
return false; | |||
} | |||
} | |||
} |
@@ -0,0 +1,421 @@ | |||
using Aliyun.OSS; | |||
using System; | |||
using log4net; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using System.Reflection; | |||
using System.IO; | |||
using static THUploadOss.Common; | |||
using Newtonsoft.Json.Linq; | |||
using Aliyun.OSS.Common; | |||
using System.Runtime.InteropServices; | |||
using System.Runtime.InteropServices.ComTypes; | |||
using System.Security.Policy; | |||
namespace THUploadOss | |||
{ | |||
public class THUploadFile | |||
{ | |||
public string m_accessKeyId; | |||
public string m_accessKeySecret; | |||
public string m_endpoint; | |||
public string m_bucketName; | |||
public string m_objectName; | |||
public string m_localPicPath; | |||
public string m_localVideoPath; | |||
private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | |||
public static float m_uploadProgressAdd = 0; | |||
public static OssClient client = null; | |||
int partSize = 1024 * 1024; //分片上传大小 | |||
public bool InitUploadFile() | |||
{ | |||
if (!getMqttConfig()) | |||
return false; | |||
return true; | |||
} | |||
public void UploadFile() | |||
{ | |||
if (DownloadFinsh == 1) | |||
{ | |||
client = new OssClient(m_endpoint, m_accessKeyId, m_accessKeySecret); | |||
string[] files1 = Directory.GetFiles(m_localVideoPath + RequestId); | |||
string[] files2 = Directory.GetFiles(m_localPicPath + RequestId); | |||
string[] files = files1.Concat(files2).ToArray(); | |||
lock (lockFileList) | |||
{ | |||
for(int i= FileList.Count-1; i>=0 ; i--) | |||
{ | |||
FileList.Remove(FileList[i]); | |||
} | |||
foreach (string file in files1) | |||
{ // 设置URL过期时间为1小时 | |||
FileStates fileState = new FileStates(); | |||
int lastIndex = file.LastIndexOf('\\'); | |||
fileState.fileName = file.Substring(lastIndex + 1); | |||
string[] endpoint = m_endpoint.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); | |||
string url = "https://" + m_bucketName + "." + endpoint[endpoint.Length - 1] + "/" + RequestId + "/" + fileState.fileName; | |||
fileState.url = url; //"oss://" +m_bucketName+"/"+ RequestId + "/" + fileState.fileName; | |||
fileState.status = 5; | |||
fileState.progress = "0.0000"; | |||
fileState.fileType = "video"; | |||
FileList.Add(fileState); | |||
} | |||
foreach (string file in files2) | |||
{ | |||
FileStates fileState = new FileStates(); | |||
int lastIndex = file.LastIndexOf('\\'); | |||
fileState.fileName = file.Substring(lastIndex + 1); | |||
string[] endpoint = m_endpoint.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); | |||
string url = "https://" + m_bucketName + "." + endpoint[endpoint.Length - 1] + "/" + RequestId + "/" + fileState.fileName; | |||
fileState.url = url; | |||
fileState.status = 5; | |||
fileState.progress = "0.0000"; | |||
fileState.fileType = "pic"; | |||
FileList.Add(fileState); | |||
} | |||
} | |||
int index = 0; | |||
foreach (string file in files) | |||
{ | |||
FileInfo fileinfo = new FileInfo(file); | |||
string[] result = file.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries); | |||
string name = result[result.Length - 1]; | |||
string objectPath = m_objectName + RequestId + "/" + name; | |||
if (fileinfo.Length == 0) | |||
{ | |||
lock (lockFileList) | |||
{ | |||
FileList.Insert(index, new FileStates() | |||
{ | |||
fileName = FileList[index].fileName, | |||
fileType = FileList[index].fileType, | |||
url = FileList[index].url, | |||
status = 15, | |||
progress = "1.0000", | |||
}); | |||
FileList.Remove(FileList[index + 1]); | |||
} | |||
index++; | |||
continue; | |||
} | |||
if (StsrtDownload == -1) | |||
{ | |||
Status = (int)UPLOAD_STATUS.Ccancellation; | |||
return ; | |||
} | |||
try | |||
{ | |||
var uploadId = InitiateMultipartUpload(this.m_bucketName, objectPath); | |||
var partETags = UploadParts(this.m_bucketName, objectPath, file, uploadId, partSize, index); | |||
if(partETags != null) | |||
{ | |||
CompleteUploadPart(this.m_bucketName, objectPath, uploadId, partETags); | |||
bool doesexist = client.DoesObjectExist(this.m_bucketName, objectPath); | |||
if (doesexist) | |||
{ | |||
lock (lockFileList) | |||
{ | |||
FileList.Insert(index, new FileStates() | |||
{ | |||
fileName = FileList[index].fileName, | |||
fileType = FileList[index].fileType, | |||
url = FileList[index].url, | |||
status = 15, | |||
progress = "1.0000", | |||
}); | |||
FileList.Remove(FileList[index + 1]); | |||
} | |||
Logger.WriteInfo("THUploadFile: " + FileList[index].fileName + " UploadFile-上传成功。"); | |||
} | |||
else | |||
{ | |||
lock (lockFileList) | |||
{ | |||
FileList.Insert(index, new FileStates() | |||
{ | |||
fileName = FileList[index].fileName, | |||
fileType = FileList[index].fileType, | |||
url = FileList[index].url, | |||
status = 20, | |||
progress = (UploadPercent).ToString(), | |||
}); | |||
FileList.Remove(FileList[index + 1]); | |||
} | |||
Logger.WriteError("THUploadFile: " + FileList[index].fileName + " UploadFile-上传失败。"); | |||
} | |||
} | |||
} | |||
catch (OssException ex) | |||
{ | |||
lock (lockFileList) | |||
{ | |||
FileList.Insert(index, new FileStates() | |||
{ | |||
fileName = FileList[index].fileName, | |||
fileType = FileList[index].fileType, | |||
url = FileList[index].url, | |||
status = 20, | |||
progress = (UploadPercent).ToString(), | |||
}); | |||
FileList.Remove(FileList[index + 1]); | |||
} | |||
Logger.WriteError("THUploadFile: " + FileList[index].fileName + " UploadFile-上传失败。" + ex.Message + "。"); | |||
} | |||
index++; | |||
} | |||
DownloadFinsh = -1; | |||
StsrtDownload = -1; | |||
Status = (int)UPLOAD_STATUS.Complete; | |||
} | |||
else | |||
System.Threading.Thread.Sleep(1000); | |||
} | |||
private static string InitiateMultipartUpload(String bucketName, String objectName) | |||
{ | |||
try | |||
{ | |||
var request = new InitiateMultipartUploadRequest(bucketName, objectName); | |||
var result = client.InitiateMultipartUpload(request); | |||
return result.UploadId; | |||
} | |||
catch | |||
{ | |||
Logger.WriteError("THUploadFile: InitiateMultipartUpload-初始化失败"); | |||
} | |||
return null; | |||
} | |||
private static List<PartETag> UploadParts(String bucketName, String objectName, String fileToUpload, String uploadId, int partSize,int index) | |||
{ | |||
m_uploadProgressAdd = 0; | |||
var fi = new FileInfo(fileToUpload); | |||
var fileSize = fi.Length;//单个文件大小 | |||
var partCount = fileSize / partSize; | |||
if (fileSize % partSize != 0) | |||
{ | |||
partCount++; | |||
} | |||
var partETags = new List<PartETag>(); | |||
try | |||
{ | |||
using (var fs = File.Open(fileToUpload, FileMode.Open)) | |||
{ | |||
for (var i = 0; i < partCount; i++) | |||
{ | |||
var skipBytes = (long)partSize * i; | |||
fs.Seek(skipBytes, 0); | |||
var size = (partSize < fileSize - skipBytes) ? partSize : (fileSize - skipBytes); | |||
m_uploadProgressAdd += size; | |||
UploadPercent = Math.Round((Double)m_uploadProgressAdd / (Double)fileSize, 4); | |||
Logger.WriteInfo("THUploadFile: UploadParts-UploadPercent= " + UploadPercent); | |||
if (StsrtDownload == -1) | |||
{ | |||
Status = (int)UPLOAD_STATUS.Ccancellation; | |||
return null; | |||
} | |||
lock (lockFileList) { | |||
FileList.Insert(index, new FileStates() | |||
{ | |||
fileName = FileList[index].fileName, | |||
fileType = FileList[index].fileType, | |||
url = FileList[index].url, | |||
status = 10, | |||
progress = (UploadPercent).ToString(), | |||
}); | |||
FileList.Remove(FileList[index + 1]); | |||
} | |||
//FileList[].progress = (UploadPercent).ToString(); | |||
var request = new UploadPartRequest(bucketName, objectName, uploadId) | |||
{ | |||
InputStream = fs, | |||
PartSize = size, | |||
PartNumber = i + 1 | |||
}; | |||
var result = client.UploadPart(request); | |||
partETags.Add(result.PartETag); | |||
} | |||
} | |||
} | |||
catch (Exception ex) | |||
{ | |||
lock (lockFileList) | |||
{ | |||
FileList.Insert(index, new FileStates() | |||
{ | |||
fileName = FileList[index].fileName, | |||
fileType = FileList[index].fileType, | |||
url = FileList[index].url, | |||
status = 20, | |||
progress = (UploadPercent).ToString(), | |||
}); | |||
FileList.Remove(FileList[index + 1]); | |||
} | |||
Logger.WriteError(ex.ToString()); | |||
} | |||
return partETags; | |||
} | |||
private static CompleteMultipartUploadResult CompleteUploadPart(String bucketName, String objectName, String uploadId, List<PartETag> partETags) | |||
{ | |||
try | |||
{ | |||
var completeMultipartUploadRequest = | |||
new CompleteMultipartUploadRequest(bucketName, objectName, uploadId); | |||
foreach (var partETag in partETags) | |||
{ | |||
completeMultipartUploadRequest.PartETags.Add(partETag); | |||
} | |||
return client.CompleteMultipartUpload(completeMultipartUploadRequest); | |||
}catch (Exception ex) | |||
{ | |||
Logger.WriteError(ex.ToString()); | |||
} | |||
return null; | |||
} | |||
//实现删除指定文件夹下的所有文件 | |||
public bool RemoveAllFile(string path) | |||
{ | |||
try | |||
{ | |||
Directory.Delete(path, true); | |||
Logger.WriteInfo("THUploadFile: RemoveAllFile(" + path + ")-操作完成"); | |||
return true; | |||
} | |||
catch (Exception ex) | |||
{ | |||
Logger.WriteError("THUploadFile: RemoveAllFile(" + path + ")-发生异常:" + ex.Message); | |||
return false; | |||
} | |||
} | |||
public bool getMqttConfig() | |||
{ | |||
if (System.IO.File.Exists(ConfigPath)) | |||
{ | |||
try | |||
{ | |||
StringBuilder accessKeyId = new StringBuilder(200); | |||
GetPrivateProfileString("ALIYUN", "accessKeyId", "配置文件存在,读取未成功!", accessKeyId, 255, ConfigPath); | |||
m_accessKeyId = accessKeyId.ToString(); | |||
StringBuilder accessKeySecret = new StringBuilder(200); | |||
GetPrivateProfileString("ALIYUN", "accessKeySecret", "配置文件存在,读取未成功!", accessKeySecret, 255, ConfigPath); | |||
m_accessKeySecret = accessKeySecret.ToString(); | |||
StringBuilder endpoint = new StringBuilder(200); | |||
GetPrivateProfileString("ALIYUN", "endpoint", "配置文件存在,读取未成功!", endpoint, 255, ConfigPath); | |||
m_endpoint = endpoint.ToString(); | |||
StringBuilder bucketName = new StringBuilder(200); | |||
GetPrivateProfileString("ALIYUN", "bucketName", "配置文件存在,读取未成功!", bucketName, 255, ConfigPath); | |||
m_bucketName = bucketName.ToString(); | |||
StringBuilder objectName = new StringBuilder(200); | |||
GetPrivateProfileString("ALIYUN", "objectName", "配置文件存在,读取未成功!", objectName, 255, ConfigPath); | |||
m_objectName = objectName.ToString(); | |||
StringBuilder localPicPath = new StringBuilder(10); | |||
GetPrivateProfileString("SMBPATH", "localPicPath", "配置文件存在,读取未成功!", localPicPath, 255, ConfigPath); | |||
m_localPicPath = localPicPath.ToString(); | |||
StringBuilder localVideoPath = new StringBuilder(10); | |||
GetPrivateProfileString("SMBPATH", "localVideoPath", "配置文件存在,读取未成功!", localVideoPath, 255, ConfigPath); | |||
m_localVideoPath = localVideoPath.ToString(); | |||
return true; | |||
} | |||
catch (Exception ex) | |||
{ | |||
Logger.WriteError("THUploadFile: "+ ex.Message.ToString()); | |||
return false; | |||
} | |||
} | |||
return false; | |||
} | |||
} | |||
} | |||
//public int UploadFile() | |||
//{ | |||
// if (DownloadFinsh == 1) | |||
// { | |||
// string[] files = Directory.GetFiles(m_localPath + RequestId); | |||
// long fileSize = 0; | |||
// foreach (string file in files) | |||
// { | |||
// FileInfo fileinfo = new FileInfo(file); | |||
// fileSize += fileinfo.Length; | |||
// } | |||
// foreach (string file in files) | |||
// { | |||
// FileInfo fileinfo = new FileInfo(file); | |||
// long len = fileinfo.Length; | |||
// float process = 0; | |||
// Console.WriteLine(file); | |||
// string[] result = file.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries); | |||
// string name = result[result.Length - 1]; | |||
// Console.WriteLine(name); | |||
// string objectPath = m_objectName; | |||
// objectPath = objectPath + RequestId + "/" + name; | |||
// var fs = File.Open(file, FileMode.Open); | |||
// var client = new OssClient(m_endpoint, m_accessKeyId, m_accessKeySecret); | |||
// PutObjectRequest putObjectRequest = new PutObjectRequest(m_bucketName, objectPath, fs); | |||
// putObjectRequest.StreamTransferProgress += (obg, args) => | |||
// { | |||
// float putProcess = (args.TransferredBytes * 100 / args.TotalBytes) / 100.0f; | |||
// // action.Invoke(putProcess); | |||
// if (putProcess >= 1) | |||
// { | |||
// // complete?.Invoke(); | |||
// putObjectRequest.StreamTransferProgress = null; | |||
// } | |||
// process = (putProcess * len) / fileSize; | |||
// if ((m_uploadProgressAdd + putProcess) >= 0.01) | |||
// { | |||
// if (putProcess == 1) | |||
// { | |||
// m_uploadProgressAdd += process; | |||
// UploadPercent = m_uploadProgressAdd * 100; | |||
// } | |||
// else | |||
// { | |||
// UploadPercent = (m_uploadProgressAdd + process) *100; | |||
// } | |||
// Console.WriteLine(UploadPercent.ToString()); | |||
// } | |||
// }; | |||
// try | |||
// { | |||
// client.PutObject(putObjectRequest); | |||
// } catch (Exception ex) | |||
// { | |||
// Console.WriteLine(ex.Message); | |||
// return -1; | |||
// } | |||
// } | |||
// DownloadFinsh = 0; | |||
// UploadFinsh = 1; | |||
// Status = (int)UPLOAD_STATUS.Complete; | |||
// return 0; | |||
// } | |||
// return -1; | |||
//} |
@@ -0,0 +1,103 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> | |||
<PropertyGroup> | |||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> | |||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> | |||
<ProjectGuid>{62FDE986-F39F-486A-85FE-B0E27AB23D25}</ProjectGuid> | |||
<OutputType>Exe</OutputType> | |||
<RootNamespace>THUploadOss</RootNamespace> | |||
<AssemblyName>THUploadOss</AssemblyName> | |||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> | |||
<FileAlignment>512</FileAlignment> | |||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> | |||
<Deterministic>true</Deterministic> | |||
</PropertyGroup> | |||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | |||
<PlatformTarget>AnyCPU</PlatformTarget> | |||
<DebugSymbols>true</DebugSymbols> | |||
<DebugType>full</DebugType> | |||
<Optimize>false</Optimize> | |||
<OutputPath>bin\Debug\</OutputPath> | |||
<DefineConstants>DEBUG;TRACE</DefineConstants> | |||
<ErrorReport>prompt</ErrorReport> | |||
<WarningLevel>4</WarningLevel> | |||
</PropertyGroup> | |||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> | |||
<PlatformTarget>AnyCPU</PlatformTarget> | |||
<DebugType>pdbonly</DebugType> | |||
<Optimize>false</Optimize> | |||
<OutputPath>bin\Release\</OutputPath> | |||
<DefineConstants>TRACE</DefineConstants> | |||
<ErrorReport>prompt</ErrorReport> | |||
<WarningLevel>4</WarningLevel> | |||
</PropertyGroup> | |||
<PropertyGroup> | |||
<ApplicationIcon>MediaTool.ico</ApplicationIcon> | |||
</PropertyGroup> | |||
<PropertyGroup /> | |||
<PropertyGroup /> | |||
<PropertyGroup /> | |||
<PropertyGroup> | |||
<NoWin32Manifest>true</NoWin32Manifest> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<Reference Include="Aliyun.OSS, Version=2.13.0.0, Culture=neutral, PublicKeyToken=0ad4175f0dac0b9b, processorArchitecture=MSIL"> | |||
<HintPath>..\packages\Aliyun.OSS.SDK.2.13.0\lib\net45\Aliyun.OSS.dll</HintPath> | |||
</Reference> | |||
<Reference Include="log4net, Version=2.0.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL"> | |||
<HintPath>..\packages\log4net.2.0.15\lib\net45\log4net.dll</HintPath> | |||
</Reference> | |||
<Reference Include="M2Mqtt.Net, Version=4.3.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
<HintPath>..\packages\M2Mqtt.4.3.0.0\lib\net45\M2Mqtt.Net.dll</HintPath> | |||
</Reference> | |||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> | |||
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath> | |||
</Reference> | |||
<Reference Include="System" /> | |||
<Reference Include="System.Configuration" /> | |||
<Reference Include="System.Core" /> | |||
<Reference Include="System.Web" /> | |||
<Reference Include="System.Windows.Forms" /> | |||
<Reference Include="System.Xml.Linq" /> | |||
<Reference Include="System.Data.DataSetExtensions" /> | |||
<Reference Include="Microsoft.CSharp" /> | |||
<Reference Include="System.Data" /> | |||
<Reference Include="System.Net.Http" /> | |||
<Reference Include="System.Xml" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<Compile Include="Logger.cs" /> | |||
<Compile Include="Program.cs" /> | |||
<Compile Include="Properties\AssemblyInfo.cs" /> | |||
<Compile Include="Properties\Resources.Designer.cs"> | |||
<AutoGen>True</AutoGen> | |||
<DesignTime>True</DesignTime> | |||
<DependentUpon>Resources.resx</DependentUpon> | |||
</Compile> | |||
<Compile Include="THDownloadFile.cs" /> | |||
<Compile Include="THHttpServe.cs" /> | |||
<Compile Include="THMqttClinet.cs" /> | |||
<Compile Include="THUploadFile.cs" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<None Include="App.config" /> | |||
<None Include="config.ini"> | |||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | |||
</None> | |||
<None Include="log4net.config"> | |||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | |||
</None> | |||
<None Include="packages.config" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<EmbeddedResource Include="Properties\Resources.resx"> | |||
<Generator>ResXFileCodeGenerator</Generator> | |||
<LastGenOutput>Resources.Designer.cs</LastGenOutput> | |||
</EmbeddedResource> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<Content Include="MediaTool.ico" /> | |||
</ItemGroup> | |||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | |||
</Project> |
@@ -0,0 +1,31 @@ | |||
[SWITCH] | |||
mqtt=true | |||
[MQTT] | |||
clientId=THJSQ03A2303SHWD6F1 | |||
airportCode=00000THJSQ23200 | |||
brokerAddress=106.15.120.154 | |||
brokerPort=1883 | |||
username=admin | |||
password=admin##123 | |||
uploadSubTopic=/v1/&/media/upload | |||
uploadResTopic=/v1/&/media/result | |||
rtmpSubTic=/v1/&/rtmp/live | |||
rtmpResTopic=/v1/&/rtmp/result | |||
[ALIYUN] | |||
accessKeyId=LTAI5tSJ62TLMUb4SZuf285A | |||
accessKeySecret=MWYynm30filZ7x0HqSHlU3pdLVNeI7 | |||
endpoint=https://oss-cn-shanghai.aliyuncs.com | |||
bucketName=th-airprt-media | |||
objectName= | |||
[SMBPATH] | |||
smbPicPath=\\192.168.144.25\camera\picture\jpg_2k\ | |||
smbVideoPath=\\192.168.144.25\camera\video\video_2k\ | |||
localPicPath=D:\MediaFile\Pic\ | |||
localVideoPath=D:\MediaFile\Video\ | |||
deleteTime=30 | |||
[HTTP] | |||
listenerUrl=http://127.0.0.1:8000/ |
@@ -0,0 +1,58 @@ | |||
<?xml version="1.0" encoding="utf-8" ?> | |||
<configuration> | |||
<configSections> | |||
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/> | |||
</configSections> | |||
<log4net> | |||
<logger name="logerror"> | |||
<appender-ref ref="ErrorAppender" /> | |||
</logger> | |||
<!-- 信息日志类 --> | |||
<logger name="loginfo"> | |||
<appender-ref ref="InfoAppender" /> | |||
</logger> | |||
<!--定义输出到文件中--> | |||
<appender name="InfoAppender" type="log4net.Appender.RollingFileAppender"> | |||
<!--定义文件存放位置--> | |||
<file value="log\\"/> | |||
<appendToFile value="true"/> | |||
<rollingStyle value="Date"/> | |||
<datePattern value="yyyyMMdd'.log'"/> | |||
<staticLogFileName value="false"/> | |||
<!--定义文件最大个数,超过按顺序删除--> | |||
<param name="MaxSizeRollBackups" value="100"/> | |||
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> | |||
<maximumFileSize value="10MB" /> | |||
<layout type="log4net.Layout.PatternLayout"> | |||
<!--每条日志末尾的文字说明--> | |||
<!--输出格式--> | |||
<!--样例:2008-03-26 13:42:32,111 [10] INFO Log4NetDemo.MainClass [(null)] - info--> | |||
<conversionPattern value="%date: %message%newline %n"/> | |||
</layout> | |||
</appender> | |||
<appender name="ErrorAppender" type="log4net.Appender.RollingFileAppender"> | |||
<!--定义文件存放位置--> | |||
<file value="log\\"/> | |||
<appendToFile value="true"/> | |||
<rollingStyle value="Date"/> | |||
<datePattern value="yyyyMMdd'.log'"/> | |||
<staticLogFileName value="false"/> | |||
<!--定义文件最大个数,超过按顺序删除--> | |||
<param name="MaxSizeRollBackups" value="100"/> | |||
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> | |||
<maximumFileSize value="10MB" /> | |||
<filter type="log4net.Filter.LevelRangeFilter"> | |||
<levelMin value="Error" /> | |||
<levelMax value="Error" /> | |||
</filter> | |||
<layout type="log4net.Layout.PatternLayout"> | |||
<!--每条日志末尾的文字说明--> | |||
<!--输出格式--> | |||
<!--样例:2008-03-26 13:42:32,111 [10] INFO Log4NetDemo.MainClass [(null)] - info--> | |||
<conversionPattern value="%date: %message%newline %n"/> | |||
</layout> | |||
</appender> | |||
</log4net> | |||
</configuration> |
@@ -0,0 +1,7 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<packages> | |||
<package id="Aliyun.OSS.SDK" version="2.13.0" targetFramework="net472" /> | |||
<package id="log4net" version="2.0.15" targetFramework="net472" /> | |||
<package id="M2Mqtt" version="4.3.0.0" targetFramework="net472" /> | |||
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net472" /> | |||
</packages> |
@@ -0,0 +1,103 @@ | |||
; 该脚本使用 HM VNISEdit 脚本编辑器向导产生 | |||
; 安装程序初始定义常量 | |||
!define PRODUCT_NAME "MediaTool" | |||
!define PRODUCT_VERSION "1.0.1" | |||
!define PRODUCT_PUBLISHER "TH" | |||
!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\THUploadOss.exe" | |||
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" | |||
!define PRODUCT_UNINST_ROOT_KEY "HKLM" | |||
SetCompressor lzma | |||
; ------ MUI 现代界面定义 (1.67 版本以上兼容) ------ | |||
!include "MUI.nsh" | |||
; MUI 预定义常量 | |||
!define MUI_ABORTWARNING | |||
!define MUI_ICON "D:\CodeBackupPackage\THupload-Oss\THUploadOss\MediaTool.ico" | |||
!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico" | |||
; 欢迎页面 | |||
!insertmacro MUI_PAGE_WELCOME | |||
; 安装目录选择页面 | |||
!insertmacro MUI_PAGE_DIRECTORY | |||
; 安装过程页面 | |||
!insertmacro MUI_PAGE_INSTFILES | |||
; 安装完成页面 | |||
!define MUI_FINISHPAGE_RUN "$INSTDIR\THUploadOss.exe" | |||
!insertmacro MUI_PAGE_FINISH | |||
; 安装卸载过程页面 | |||
!insertmacro MUI_UNPAGE_INSTFILES | |||
; 安装界面包含的语言设置 | |||
!insertmacro MUI_LANGUAGE "SimpChinese" | |||
; 安装预释放文件 | |||
!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS | |||
; ------ MUI 现代界面定义结束 ------ | |||
Name "${PRODUCT_NAME} ${PRODUCT_VERSION}" | |||
OutFile "MediaTool.exe" | |||
InstallDir "$PROGRAMFILES\MediaTool" | |||
InstallDirRegKey HKLM "${PRODUCT_UNINST_KEY}" "UninstallString" | |||
ShowInstDetails show | |||
ShowUnInstDetails show | |||
Section "MainSection" SEC01 | |||
SetOutPath "$INSTDIR" | |||
SetOverwrite ifnewer | |||
File /r "D:\CodeBackupPackage\THupload-Oss\THUploadOss\bin\Release\*.*" | |||
CreateDirectory "$SMPROGRAMS\MediaTool" | |||
CreateShortCut "$SMPROGRAMS\MediaTool\MediaTool.lnk" "$INSTDIR\THUploadOss.exe" | |||
CreateShortCut "$DESKTOP\MediaTool.lnk" "$INSTDIR\THUploadOss.exe" | |||
File "D:\CodeBackupPackage\THupload-Oss\THUploadOss\bin\Release\THUploadOss.exe" | |||
SectionEnd | |||
Section -AdditionalIcons | |||
CreateShortCut "$SMPROGRAMS\MediaTool\Uninstall.lnk" "$INSTDIR\uninst.exe" | |||
SectionEnd | |||
Section -Post | |||
WriteUninstaller "$INSTDIR\uninst.exe" | |||
WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\THUploadOss.exe" | |||
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)" | |||
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe" | |||
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\THUploadOss.exe" | |||
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}" | |||
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}" | |||
SectionEnd | |||
/****************************** | |||
* 以下是安装程序的卸载部分 * | |||
******************************/ | |||
Section Uninstall | |||
Delete "$INSTDIR\uninst.exe" | |||
Delete "$INSTDIR\THUploadOss.exe" | |||
Delete "$SMPROGRAMS\MediaTool\Uninstall.lnk" | |||
Delete "$DESKTOP\MediaTool.lnk" | |||
Delete "$SMPROGRAMS\MediaTool\MediaTool.lnk" | |||
RMDir "$SMPROGRAMS\MediaTool" | |||
RMDir "$INSTDIR" | |||
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" | |||
DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}" | |||
SetAutoClose true | |||
SectionEnd | |||
#-- 根据 NSIS 脚本编辑规则,所有 Function 区段必须放置在 Section 区段之后编写,以避免安装程序出现未可预知的问题。--# | |||
Function un.onInit | |||
MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "您确实要完全移除 $(^Name) ,及其所有的组件?" IDYES +2 | |||
Abort | |||
FunctionEnd | |||
Function un.onUninstSuccess | |||
HideWindow | |||
MessageBox MB_ICONINFORMATION|MB_OK "$(^Name) 已成功地从您的计算机移除。" | |||
FunctionEnd |
@@ -0,0 +1,20 @@ | |||
The MIT License (MIT) | |||
Copyright (c) 2007 James Newton-King | |||
Permission is hereby granted, free of charge, to any person obtaining a copy of | |||
this software and associated documentation files (the "Software"), to deal in | |||
the Software without restriction, including without limitation the rights to | |||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | |||
the Software, and to permit persons to whom the Software is furnished to do so, | |||
subject to the following conditions: | |||
The above copyright notice and this permission notice shall be included in all | |||
copies or substantial portions of the Software. | |||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | |||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | |||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | |||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
@@ -0,0 +1,71 @@ | |||
# ![Logo](https://raw.githubusercontent.com/JamesNK/Newtonsoft.Json/master/Doc/icons/logo.jpg) Json.NET | |||
[![NuGet version (Newtonsoft.Json)](https://img.shields.io/nuget/v/Newtonsoft.Json.svg?style=flat-square)](https://www.nuget.org/packages/Newtonsoft.Json/) | |||
[![Build status](https://dev.azure.com/jamesnk/Public/_apis/build/status/JamesNK.Newtonsoft.Json?branchName=master)](https://dev.azure.com/jamesnk/Public/_build/latest?definitionId=8) | |||
Json.NET is a popular high-performance JSON framework for .NET | |||
## Serialize JSON | |||
```csharp | |||
Product product = new Product(); | |||
product.Name = "Apple"; | |||
product.Expiry = new DateTime(2008, 12, 28); | |||
product.Sizes = new string[] { "Small" }; | |||
string json = JsonConvert.SerializeObject(product); | |||
// { | |||
// "Name": "Apple", | |||
// "Expiry": "2008-12-28T00:00:00", | |||
// "Sizes": [ | |||
// "Small" | |||
// ] | |||
// } | |||
``` | |||
## Deserialize JSON | |||
```csharp | |||
string json = @"{ | |||
'Name': 'Bad Boys', | |||
'ReleaseDate': '1995-4-7T00:00:00', | |||
'Genres': [ | |||
'Action', | |||
'Comedy' | |||
] | |||
}"; | |||
Movie m = JsonConvert.DeserializeObject<Movie>(json); | |||
string name = m.Name; | |||
// Bad Boys | |||
``` | |||
## LINQ to JSON | |||
```csharp | |||
JArray array = new JArray(); | |||
array.Add("Manual text"); | |||
array.Add(new DateTime(2000, 5, 23)); | |||
JObject o = new JObject(); | |||
o["MyArray"] = array; | |||
string json = o.ToString(); | |||
// { | |||
// "MyArray": [ | |||
// "Manual text", | |||
// "2000-05-23T00:00:00" | |||
// ] | |||
// } | |||
``` | |||
## Links | |||
- [Homepage](https://www.newtonsoft.com/json) | |||
- [Documentation](https://www.newtonsoft.com/json/help) | |||
- [NuGet Package](https://www.nuget.org/packages/Newtonsoft.Json) | |||
- [Release Notes](https://github.com/JamesNK/Newtonsoft.Json/releases) | |||
- [Contributing Guidelines](https://github.com/JamesNK/Newtonsoft.Json/blob/master/CONTRIBUTING.md) | |||
- [License](https://github.com/JamesNK/Newtonsoft.Json/blob/master/LICENSE.md) | |||
- [Stack Overflow](https://stackoverflow.com/questions/tagged/json.net) |