生成单文件

This commit is contained in:
2025-09-26 17:42:33 +08:00
parent 0884292626
commit 13b838c7c7
17 changed files with 1671 additions and 206 deletions

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +1,11 @@
using HandyControl.Collections; using HandyControl.Collections;
using System;
using System.Configuration; using System.Configuration;
using System.Data; using System.Data;
using System.Diagnostics; using System.Diagnostics;
using System.IO;
using System.Windows; using System.Windows;
using .Utility.Extension;
namespace namespace
{ {
@@ -13,6 +16,7 @@ namespace 电子展板
{ {
public App() public App()
{ {
} }
} }

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,5 @@
using Nancy.Hosting.Self; //using Nancy;
//using Nancy.Hosting.Self;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@@ -13,7 +14,7 @@ namespace 电子展板.Base
{ {
public class GlobalVariable public class GlobalVariable
{ {
public static NancyHost WebServer; //public static NancyHost WebServer;
private static MyConfig _config; private static MyConfig _config;
/// <summary> /// <summary>
@@ -24,7 +25,38 @@ namespace 电子展板.Base
get get
{ {
if (_config == null) if (_config == null)
_config = File.ReadAllText(MyEnvironment.Root("/Configs/Config.json")).ToObject<MyConfig>(); {
try
{
_config = File.ReadAllText(MyEnvironment.Root("/Config.json"), Encoding.UTF8).ToObject<MyConfig>();
//删除缓存没用到的图片
List<string> list = new List<string>
{
_config.CPCMember1Path,
_config.CPCMember2Path,
_config.CPCMember3Path,
_config.CPCMember4Path
};
list = list.Where(it => !it.IsNullOrEmpty()).Select(it => it.Replace("/upload/", "")).ToList();
if (_config.FileUploadList == null)
_config.FileUploadList = new List<UploadFiles>();
_config.FileUploadList = _config.FileUploadList.Where(it => list.Contains(it.Name)).ToList();
File.WriteAllText(MyEnvironment.Root("/Config.json"), _config.ToJson(), Encoding.UTF8);
}
catch (Exception ex)
{
string packUri = $"pack://application:,,,/Assets/InitConfig.json";
string json = "";
using (Stream stream = System.Windows.Application.GetResourceStream(new Uri(packUri, UriKind.RelativeOrAbsolute)).Stream)
{
using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
{
json = new StreamReader(stream, Encoding.UTF8).ReadToEnd();
}
}
_config = json.ToObject<MyConfig>();
}
}
return _config; return _config;
} }
set set
@@ -35,7 +67,7 @@ namespace 电子展板.Base
public static void SaveConfig() public static void SaveConfig()
{ {
File.WriteAllText(MyEnvironment.Root("/Configs/Config.json"), Config.ToJson()); File.WriteAllText(MyEnvironment.Root("/Config.json"), Config.ToJson(), Encoding.UTF8);
} }
} }
} }

View File

@@ -1,4 +1,4 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> <Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<PropertyChanged /> <PropertyChanged />
<!--<Costura />--> <Costura />
</Weavers> </Weavers>

View File

@@ -53,6 +53,157 @@
</xs:attribute> </xs:attribute>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
<xs:element name="Costura" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:all>
<xs:element minOccurs="0" maxOccurs="1" name="ExcludeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="IncludeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="ExcludeRuntimeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="IncludeRuntimeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="Unmanaged32Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>Obsolete, use UnmanagedWinX86Assemblies instead</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="UnmanagedWinX86Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged X86 (32 bit) assembly names to include, delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="Unmanaged64Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>Obsolete, use UnmanagedWinX64Assemblies instead.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="UnmanagedWinX64Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged X64 (64 bit) assembly names to include, delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="UnmanagedWinArm64Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged Arm64 (64 bit) assembly names to include, delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="PreloadOrder" type="xs:string">
<xs:annotation>
<xs:documentation>The order of preloaded assemblies, delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:all>
<xs:attribute name="CreateTemporaryAssemblies" type="xs:boolean">
<xs:annotation>
<xs:documentation>This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="IncludeDebugSymbols" type="xs:boolean">
<xs:annotation>
<xs:documentation>Controls if .pdbs for reference assemblies are also embedded.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="IncludeRuntimeReferences" type="xs:boolean">
<xs:annotation>
<xs:documentation>Controls if runtime assemblies are also embedded.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="UseRuntimeReferencePaths" type="xs:boolean">
<xs:annotation>
<xs:documentation>Controls whether the runtime assemblies are embedded with their full path or only with their assembly name.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="DisableCompression" type="xs:boolean">
<xs:annotation>
<xs:documentation>Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="DisableCleanup" type="xs:boolean">
<xs:annotation>
<xs:documentation>As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="DisableEventSubscription" type="xs:boolean">
<xs:annotation>
<xs:documentation>The attach method no longer subscribes to the `AppDomain.AssemblyResolve` (.NET 4.x) and `AssemblyLoadContext.Resolving` (.NET 6.0+) events.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="LoadAtModuleInit" type="xs:boolean">
<xs:annotation>
<xs:documentation>Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="IgnoreSatelliteAssemblies" type="xs:boolean">
<xs:annotation>
<xs:documentation>Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="ExcludeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with |</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="IncludeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="ExcludeRuntimeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with |</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="IncludeRuntimeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="Unmanaged32Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>Obsolete, use UnmanagedWinX86Assemblies instead</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="UnmanagedWinX86Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged X86 (32 bit) assembly names to include, delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="Unmanaged64Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>Obsolete, use UnmanagedWinX64Assemblies instead</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="UnmanagedWinX64Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged X64 (64 bit) assembly names to include, delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="UnmanagedWinArm64Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged Arm64 (64 bit) assembly names to include, delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="PreloadOrder" type="xs:string">
<xs:annotation>
<xs:documentation>The order of preloaded assemblies, delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:all> </xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean"> <xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation> <xs:annotation>

View File

@@ -1,7 +1,9 @@
using Nancy.Swagger.Annotations.Attributes; using Nancy.Swagger.Annotations.Attributes;
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Windows.Documents;
using .Base; using .Base;
namespace .Models namespace .Models
@@ -118,51 +120,8 @@ namespace 电子展板.Models
[Comment("党员字体大小")] [Comment("党员字体大小")]
[ModelProperty(Description = "党员字体大小", Required = true, Minimum = 15, Maximum = 60)] [ModelProperty(Description = "党员字体大小", Required = true, Minimum = 15, Maximum = 60)]
public int CPCMemberSize { get; set; } public int CPCMemberSize { get; set; }
/// <summary>
/// 转换成JSON字符串 public List<UploadFiles> FileUploadList { get; set; }
/// </summary>
/// <returns></returns>
//public string ToJson()
//{
// StringBuilder sb = new StringBuilder();
// sb.AppendLine("{");
// //得到所有的Property
// var properties = GetType().GetProperties();
// for (int i = 0; i < properties.Length; i++)
// {
// var property = properties[i];
// string endChar = ",";
// if (i == properties.Length - 1)
// {
// endChar = "";
// }
// var comment = property.GetCustomAttributes(typeof(CommentAttribute), false).FirstOrDefault() as CommentAttribute;
// string commentText = "";
// if (comment != null)
// {
// commentText = $" /* {comment.Comment} */";
// }
// string propertyName = property.Name;
// var value = property.GetValue(this, null);
// if (value != null)
// {
// var valueType = value.GetType();
// if (valueType == typeof(string))
// {
// string value1 = (string)value;
// value1 = value1.Replace("\"", "\\\"");
// value1 = value1.Replace("\r\n", "\\r\\n");
// sb.AppendLine($" \"{propertyName}\":\"{value1}\"{endChar}{commentText}");
// }
// else
// {
// sb.AppendLine($" \"{propertyName}\":{value}{endChar}{commentText}");
// }
// }
// }
// sb.AppendLine("}");
// return sb.ToString();
//}
} }

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace .Models
{
public class UploadFiles
{
public string Name { get; set; }
public byte[] Bin { get; set; }
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

View File

@@ -0,0 +1,928 @@
using System;
using System.IO;
using System.Text;
namespace .Utility
{
public class ByteArrayStream : Stream
{
private byte[] _buffer;
private int _position;
private int _length;
private int _capacity;
private Encoding _defaultEncoding = Encoding.UTF8;
// 默认编码方式(用于字符串读写)
public Encoding DefaultEncoding
{
get => _defaultEncoding;
set => _defaultEncoding = value ?? throw new ArgumentNullException(nameof(value));
}
// 构造函数:创建指定初始容量的流
public ByteArrayStream(int initialCapacity = 4096)
{
if (initialCapacity < 0)
throw new ArgumentOutOfRangeException(nameof(initialCapacity));
_capacity = initialCapacity;
_buffer = new byte[initialCapacity];
_position = 0;
_length = 0;
}
// 构造函数:从现有字节数组创建流
public ByteArrayStream(byte[] buffer)
{
if (buffer == null)
throw new ArgumentNullException(nameof(buffer));
_buffer = buffer;
_capacity = buffer.Length;
_length = buffer.Length;
_position = 0;
}
// 指示当前流是否支持读取
public override bool CanRead => true;
// 指示当前流是否支持查找
public override bool CanSeek => true;
// 指示当前流是否支持写入
public override bool CanWrite => true;
// 获取流的长度
public override long Length => _length;
// 获取或设置当前流中的位置
public override long Position
{
get => _position;
set
{
if (value < 0 || value > _length)
throw new ArgumentOutOfRangeException(nameof(value));
_position = (int)value;
}
}
// 确保有足够的容量
private void EnsureCapacity(int required)
{
if (required <= _capacity) return;
// 每次扩容为当前容量的2倍或所需容量取较大值
int newCapacity = Math.Max(_capacity * 2, required);
byte[] newBuffer = new byte[newCapacity];
Array.Copy(_buffer, newBuffer, _length);
_buffer = newBuffer;
_capacity = newCapacity;
}
public override void Flush()
{
// 内存流无需实际刷新
}
public override int Read(byte[] buffer, int offset, int count)
{
if (buffer == null)
throw new ArgumentNullException(nameof(buffer));
if (offset < 0)
throw new ArgumentOutOfRangeException(nameof(offset));
if (count < 0)
throw new ArgumentOutOfRangeException(nameof(count));
if (offset + count > buffer.Length)
throw new ArgumentException("偏移量和计数的总和超过缓冲区长度");
int bytesToRead = Math.Min(count, _length - _position);
if (bytesToRead > 0)
{
Array.Copy(_buffer, _position, buffer, offset, bytesToRead);
_position += bytesToRead;
}
return bytesToRead;
}
public override long Seek(long offset, SeekOrigin origin)
{
long newPosition;
switch (origin)
{
case SeekOrigin.Begin:
newPosition = offset;
break;
case SeekOrigin.Current:
newPosition = _position + offset;
break;
case SeekOrigin.End:
newPosition = _length + offset;
break;
default:
throw new ArgumentOutOfRangeException(nameof(origin));
}
if (newPosition < 0 || newPosition > _length)
throw new IOException("seek 位置无效");
_position = (int)newPosition;
return _position;
}
public override void SetLength(long value)
{
if (value < 0 || value > int.MaxValue)
throw new ArgumentOutOfRangeException(nameof(value));
int newLength = (int)value;
EnsureCapacity(newLength);
_length = newLength;
if (_position > newLength)
_position = newLength;
}
public override void Write(byte[] buffer, int offset, int count)
{
if (buffer == null)
throw new ArgumentNullException(nameof(buffer));
if (offset < 0)
throw new ArgumentOutOfRangeException(nameof(offset));
if (count < 0)
throw new ArgumentOutOfRangeException(nameof(count));
if (offset + count > buffer.Length)
throw new ArgumentException("偏移量和计数的总和超过缓冲区长度");
if (count == 0) return;
int newPosition = _position + count;
if (newPosition > _length)
{
EnsureCapacity(newPosition);
_length = newPosition;
}
Array.Copy(buffer, offset, _buffer, _position, count);
_position = newPosition;
}
#region -
/// <summary>
/// 读取一个字节
/// </summary>
public new byte ReadByte()
{
if (_position >= _length)
throw new EndOfStreamException("已到达流的末尾");
return _buffer[_position++];
}
/// <summary>
/// 写入一个字节
/// </summary>
public new void WriteByte(byte value)
{
EnsureCapacity(_position + 1);
if (_position == _length)
_length++;
_buffer[_position++] = value;
}
/// <summary>
/// 读取16位有符号整数小端字节序
/// </summary>
public short ReadInt16()
{
return ReadInt16(Endianness.LittleEndian);
}
/// <summary>
/// 读取16位有符号整数
/// </summary>
public short ReadInt16(Endianness endianness)
{
byte[] bytes = ReadBytes(2);
if (NeedReverse(endianness))
Array.Reverse(bytes);
return BitConverter.ToInt16(bytes, 0);
}
/// <summary>
/// 写入16位有符号整数小端字节序
/// </summary>
public void WriteInt16(short value)
{
WriteInt16(value, Endianness.LittleEndian);
}
/// <summary>
/// 写入16位有符号整数
/// </summary>
public void WriteInt16(short value, Endianness endianness)
{
byte[] bytes = BitConverter.GetBytes(value);
if (NeedReverse(endianness))
Array.Reverse(bytes);
Write(bytes, 0, bytes.Length);
}
/// <summary>
/// 读取16位无符号整数小端字节序
/// </summary>
public ushort ReadUInt16()
{
return ReadUInt16(Endianness.LittleEndian);
}
/// <summary>
/// 读取16位无符号整数
/// </summary>
public ushort ReadUInt16(Endianness endianness)
{
byte[] bytes = ReadBytes(2);
if (NeedReverse(endianness))
Array.Reverse(bytes);
return BitConverter.ToUInt16(bytes, 0);
}
/// <summary>
/// 写入16位无符号整数小端字节序
/// </summary>
public void WriteUInt16(ushort value)
{
WriteUInt16(value, Endianness.LittleEndian);
}
/// <summary>
/// 写入16位无符号整数
/// </summary>
public void WriteUInt16(ushort value, Endianness endianness)
{
byte[] bytes = BitConverter.GetBytes(value);
if (NeedReverse(endianness))
Array.Reverse(bytes);
Write(bytes, 0, bytes.Length);
}
/// <summary>
/// 读取32位有符号整数小端字节序
/// </summary>
public int ReadInt32()
{
return ReadInt32(Endianness.LittleEndian);
}
/// <summary>
/// 读取32位有符号整数
/// </summary>
public int ReadInt32(Endianness endianness)
{
byte[] bytes = ReadBytes(4);
if (NeedReverse(endianness))
Array.Reverse(bytes);
return BitConverter.ToInt32(bytes, 0);
}
/// <summary>
/// 写入32位有符号整数小端字节序
/// </summary>
public void WriteInt32(int value)
{
WriteInt32(value, Endianness.LittleEndian);
}
/// <summary>
/// 写入32位有符号整数
/// </summary>
public void WriteInt32(int value, Endianness endianness)
{
byte[] bytes = BitConverter.GetBytes(value);
if (NeedReverse(endianness))
Array.Reverse(bytes);
Write(bytes, 0, bytes.Length);
}
/// <summary>
/// 读取32位无符号整数小端字节序
/// </summary>
public uint ReadUInt32()
{
return ReadUInt32(Endianness.LittleEndian);
}
/// <summary>
/// 读取32位无符号整数
/// </summary>
public uint ReadUInt32(Endianness endianness)
{
byte[] bytes = ReadBytes(4);
if (NeedReverse(endianness))
Array.Reverse(bytes);
return BitConverter.ToUInt32(bytes, 0);
}
/// <summary>
/// 写入32位无符号整数小端字节序
/// </summary>
public void WriteUInt32(uint value)
{
WriteUInt32(value, Endianness.LittleEndian);
}
/// <summary>
/// 写入32位无符号整数
/// </summary>
public void WriteUInt32(uint value, Endianness endianness)
{
byte[] bytes = BitConverter.GetBytes(value);
if (NeedReverse(endianness))
Array.Reverse(bytes);
Write(bytes, 0, bytes.Length);
}
/// <summary>
/// 读取64位有符号整数小端字节序
/// </summary>
public long ReadInt64()
{
return ReadInt64(Endianness.LittleEndian);
}
/// <summary>
/// 读取64位有符号整数
/// </summary>
public long ReadInt64(Endianness endianness)
{
byte[] bytes = ReadBytes(8);
if (NeedReverse(endianness))
Array.Reverse(bytes);
return BitConverter.ToInt64(bytes, 0);
}
/// <summary>
/// 写入64位有符号整数小端字节序
/// </summary>
public void WriteInt64(long value)
{
WriteInt64(value, Endianness.LittleEndian);
}
/// <summary>
/// 写入64位有符号整数
/// </summary>
public void WriteInt64(long value, Endianness endianness)
{
byte[] bytes = BitConverter.GetBytes(value);
if (NeedReverse(endianness))
Array.Reverse(bytes);
Write(bytes, 0, bytes.Length);
}
/// <summary>
/// 读取64位无符号整数小端字节序
/// </summary>
public ulong ReadUInt64()
{
return ReadUInt64(Endianness.LittleEndian);
}
/// <summary>
/// 读取64位无符号整数
/// </summary>
public ulong ReadUInt64(Endianness endianness)
{
byte[] bytes = ReadBytes(8);
if (NeedReverse(endianness))
Array.Reverse(bytes);
return BitConverter.ToUInt64(bytes, 0);
}
/// <summary>
/// 写入64位无符号整数小端字节序
/// </summary>
public void WriteUInt64(ulong value)
{
WriteUInt64(value, Endianness.LittleEndian);
}
/// <summary>
/// 写入64位无符号整数
/// </summary>
public void WriteUInt64(ulong value, Endianness endianness)
{
byte[] bytes = BitConverter.GetBytes(value);
if (NeedReverse(endianness))
Array.Reverse(bytes);
Write(bytes, 0, bytes.Length);
}
/// <summary>
/// 读取单精度浮点数(小端字节序)
/// </summary>
public float ReadFloat()
{
return ReadFloat(Endianness.LittleEndian);
}
/// <summary>
/// 读取单精度浮点数
/// </summary>
public float ReadFloat(Endianness endianness)
{
byte[] bytes = ReadBytes(4);
if (NeedReverse(endianness))
Array.Reverse(bytes);
return BitConverter.ToSingle(bytes, 0);
}
/// <summary>
/// 写入单精度浮点数(小端字节序)
/// </summary>
public void WriteFloat(float value)
{
WriteFloat(value, Endianness.LittleEndian);
}
/// <summary>
/// 写入单精度浮点数
/// </summary>
public void WriteFloat(float value, Endianness endianness)
{
byte[] bytes = BitConverter.GetBytes(value);
if (NeedReverse(endianness))
Array.Reverse(bytes);
Write(bytes, 0, bytes.Length);
}
/// <summary>
/// 读取双精度浮点数(小端字节序)
/// </summary>
public double ReadDouble()
{
return ReadDouble(Endianness.LittleEndian);
}
/// <summary>
/// 读取双精度浮点数
/// </summary>
public double ReadDouble(Endianness endianness)
{
byte[] bytes = ReadBytes(8);
if (NeedReverse(endianness))
Array.Reverse(bytes);
return BitConverter.ToDouble(bytes, 0);
}
/// <summary>
/// 写入双精度浮点数(小端字节序)
/// </summary>
public void WriteDouble(double value)
{
WriteDouble(value, Endianness.LittleEndian);
}
/// <summary>
/// 写入双精度浮点数
/// </summary>
public void WriteDouble(double value, Endianness endianness)
{
byte[] bytes = BitConverter.GetBytes(value);
if (NeedReverse(endianness))
Array.Reverse(bytes);
Write(bytes, 0, bytes.Length);
}
/// <summary>
/// 读取布尔值1字节0表示false非0表示true
/// </summary>
public bool ReadBoolean()
{
return ReadByte() != 0;
}
/// <summary>
/// 写入布尔值1字节0表示false1表示true
/// </summary>
public void WriteBoolean(bool value)
{
WriteByte(value ? (byte)1 : (byte)0);
}
/// <summary>
/// 读取字符(小端字节序)
/// </summary>
public char ReadChar()
{
return ReadChar(Endianness.LittleEndian);
}
/// <summary>
/// 读取字符
/// </summary>
public char ReadChar(Endianness endianness)
{
byte[] bytes = ReadBytes(2);
if (NeedReverse(endianness))
Array.Reverse(bytes);
return BitConverter.ToChar(bytes, 0);
}
/// <summary>
/// 写入字符(小端字节序)
/// </summary>
public void WriteChar(char value)
{
WriteChar(value, Endianness.LittleEndian);
}
/// <summary>
/// 写入字符
/// </summary>
public void WriteChar(char value, Endianness endianness)
{
byte[] bytes = BitConverter.GetBytes(value);
if (NeedReverse(endianness))
Array.Reverse(bytes);
Write(bytes, 0, bytes.Length);
}
/// <summary>
/// 读取十进制数(小端字节序)
/// </summary>
public decimal ReadDecimal()
{
return ReadDecimal(Endianness.LittleEndian);
}
/// <summary>
/// 读取十进制数
/// </summary>
public decimal ReadDecimal(Endianness endianness)
{
int[] bits = new int[4];
for (int i = 0; i < 4; i++)
{
bits[i] = ReadInt32(endianness);
}
return new decimal(bits);
}
/// <summary>
/// 写入十进制数(小端字节序)
/// </summary>
public void WriteDecimal(decimal value)
{
WriteDecimal(value, Endianness.LittleEndian);
}
/// <summary>
/// 写入十进制数
/// </summary>
public void WriteDecimal(decimal value, Endianness endianness)
{
int[] bits = decimal.GetBits(value);
foreach (int bit in bits)
{
WriteInt32(bit, endianness);
}
}
/// <summary>
/// 读取指定长度的字节数组
/// </summary>
public byte[] ReadBytes(int count)
{
if (count < 0)
throw new ArgumentOutOfRangeException(nameof(count));
if (_position + count > _length)
throw new EndOfStreamException("没有足够的字节可供读取");
byte[] result = new byte[count];
Array.Copy(_buffer, _position, result, 0, count);
_position += count;
return result;
}
#endregion
#region
/// <summary>
/// 读取以null结尾的字符串C风格字符串
/// </summary>
public string ReadNullTerminatedString()
{
return ReadNullTerminatedString(DefaultEncoding);
}
/// <summary>
/// 读取以null结尾的字符串C风格字符串
/// </summary>
public string ReadNullTerminatedString(Encoding encoding)
{
if (encoding == null)
throw new ArgumentNullException(nameof(encoding));
int startPos = _position;
// 查找null终止符
while (_position < _length && _buffer[_position] != 0)
{
_position++;
}
int byteCount = _position - startPos;
string result = encoding.GetString(_buffer, startPos, byteCount);
// 跳过null终止符
if (_position < _length)
{
_position++;
}
return result;
}
/// <summary>
/// 写入以null结尾的字符串C风格字符串
/// </summary>
public void WriteNullTerminatedString(string value)
{
WriteNullTerminatedString(value, DefaultEncoding);
}
/// <summary>
/// 写入以null结尾的字符串C风格字符串
/// </summary>
public void WriteNullTerminatedString(string value, Encoding encoding)
{
if (value == null)
throw new ArgumentNullException(nameof(value));
if (encoding == null)
throw new ArgumentNullException(nameof(encoding));
byte[] bytes = encoding.GetBytes(value);
Write(bytes, 0, bytes.Length);
WriteByte(0); // 写入null终止符
}
/// <summary>
/// 读取前缀长度的字符串(先读取长度,再读取内容)
/// 使用Int32作为长度前缀
/// </summary>
public string ReadLengthPrefixedString()
{
return ReadLengthPrefixedString(DefaultEncoding, Endianness.LittleEndian);
}
/// <summary>
/// 读取前缀长度的字符串(先读取长度,再读取内容)
/// 使用Int32作为长度前缀
/// </summary>
public string ReadLengthPrefixedString(Encoding encoding, Endianness endianness)
{
return ReadLengthPrefixedString<int>(encoding, endianness);
}
/// <summary>
/// 读取前缀长度的字符串(先读取长度,再读取内容)
/// 支持指定长度类型Int16, Int32, Int64等
/// </summary>
public string ReadLengthPrefixedString<TLength>(Encoding encoding, Endianness endianness)
where TLength : struct, IConvertible
{
if (encoding == null)
throw new ArgumentNullException(nameof(encoding));
// 读取长度前缀
TLength lengthValue = Read<TLength>(endianness);
int length = Convert.ToInt32(lengthValue);
if (length < 0)
throw new IOException("字符串长度不能为负数");
byte[] bytes = ReadBytes(length);
return encoding.GetString(bytes);
}
/// <summary>
/// 写入前缀长度的字符串(先写入长度,再写入内容)
/// 使用Int32作为长度前缀
/// </summary>
public void WriteLengthPrefixedString(string value)
{
WriteLengthPrefixedString(value, DefaultEncoding, Endianness.LittleEndian);
}
/// <summary>
/// 写入前缀长度的字符串(先写入长度,再写入内容)
/// 使用Int32作为长度前缀
/// </summary>
public void WriteLengthPrefixedString(string value, Encoding encoding, Endianness endianness)
{
WriteLengthPrefixedString<int>(value, encoding, endianness);
}
/// <summary>
/// 写入前缀长度的字符串(先写入长度,再写入内容)
/// 支持指定长度类型Int16, Int32, Int64等
/// </summary>
public void WriteLengthPrefixedString<TLength>(string value, Encoding encoding, Endianness endianness)
where TLength : struct, IConvertible
{
if (value == null)
throw new ArgumentNullException(nameof(value));
if (encoding == null)
throw new ArgumentNullException(nameof(encoding));
byte[] bytes = encoding.GetBytes(value);
// 检查长度是否在指定类型范围内
TLength lengthValue = (TLength)Convert.ChangeType(bytes.Length, typeof(TLength));
// 写入长度前缀和字符串内容
Write<TLength>(lengthValue, endianness);
Write(bytes, 0, bytes.Length);
}
/// <summary>
/// 读取固定长度的字符串
/// </summary>
public string ReadFixedLengthString(int byteCount)
{
return ReadFixedLengthString(byteCount, DefaultEncoding);
}
/// <summary>
/// 读取固定长度的字符串
/// </summary>
public string ReadFixedLengthString(int byteCount, Encoding encoding)
{
if (byteCount < 0)
throw new ArgumentOutOfRangeException(nameof(byteCount));
if (encoding == null)
throw new ArgumentNullException(nameof(encoding));
byte[] bytes = ReadBytes(byteCount);
return encoding.GetString(bytes);
}
/// <summary>
/// 写入固定长度的字符串,不足则填充,超出则截断
/// </summary>
public void WriteFixedLengthString(string value, int byteCount)
{
WriteFixedLengthString(value, byteCount, DefaultEncoding, (byte)0);
}
/// <summary>
/// 写入固定长度的字符串,不足则填充,超出则截断
/// </summary>
public void WriteFixedLengthString(string value, int byteCount, Encoding encoding, byte paddingByte)
{
if (byteCount < 0)
throw new ArgumentOutOfRangeException(nameof(byteCount));
if (encoding == null)
throw new ArgumentNullException(nameof(encoding));
if (value == null)
value = string.Empty;
// 获取字符串的字节表示
byte[] originalBytes = encoding.GetBytes(value);
// 创建目标字节数组
byte[] targetBytes = new byte[byteCount];
if (paddingByte != 0)
{
// // 填充默认值
for (int i = 0; i < byteCount; i++)
targetBytes[i] = paddingByte;
}
// 复制字节,超出部分截断
int copyLength = Math.Min(originalBytes.Length, byteCount);
Array.Copy(originalBytes, targetBytes, copyLength);
Write(targetBytes, 0, targetBytes.Length);
}
#endregion
#region
/// <summary>
/// 泛型读取方法(小端字节序)
/// </summary>
public T Read<T>() where T : struct
{
return Read<T>(Endianness.LittleEndian);
}
/// <summary>
/// 泛型读取方法
/// </summary>
public T Read<T>(Endianness endianness) where T : struct
{
Type type = typeof(T);
if (type == typeof(byte)) return (T)(object)ReadByte();
if (type == typeof(short)) return (T)(object)ReadInt16(endianness);
if (type == typeof(ushort)) return (T)(object)ReadUInt16(endianness);
if (type == typeof(int)) return (T)(object)ReadInt32(endianness);
if (type == typeof(uint)) return (T)(object)ReadUInt32(endianness);
if (type == typeof(long)) return (T)(object)ReadInt64(endianness);
if (type == typeof(ulong)) return (T)(object)ReadUInt64(endianness);
if (type == typeof(float)) return (T)(object)ReadFloat(endianness);
if (type == typeof(double)) return (T)(object)ReadDouble(endianness);
if (type == typeof(bool)) return (T)(object)ReadBoolean();
if (type == typeof(char)) return (T)(object)ReadChar(endianness);
if (type == typeof(decimal)) return (T)(object)ReadDecimal(endianness);
throw new NotSupportedException($"不支持的类型: {type.Name}");
}
/// <summary>
/// 泛型写入方法(小端字节序)
/// </summary>
public void Write<T>(T value) where T : struct
{
Write(value, Endianness.LittleEndian);
}
/// <summary>
/// 泛型写入方法
/// </summary>
public void Write<T>(T value, Endianness endianness) where T : struct
{
Type type = typeof(T);
if (type == typeof(byte)) { WriteByte((byte)(object)value); return; }
if (type == typeof(short)) { WriteInt16((short)(object)value, endianness); return; }
if (type == typeof(ushort)) { WriteUInt16((ushort)(object)value, endianness); return; }
if (type == typeof(int)) { WriteInt32((int)(object)value, endianness); return; }
if (type == typeof(uint)) { WriteUInt32((uint)(object)value, endianness); return; }
if (type == typeof(long)) { WriteInt64((long)(object)value, endianness); return; }
if (type == typeof(ulong)) { WriteUInt64((ulong)(object)value, endianness); return; }
if (type == typeof(float)) { WriteFloat((float)(object)value, endianness); return; }
if (type == typeof(double)) { WriteDouble((double)(object)value, endianness); return; }
if (type == typeof(bool)) { WriteBoolean((bool)(object)value); return; }
if (type == typeof(char)) { WriteChar((char)(object)value, endianness); return; }
if (type == typeof(decimal)) { WriteDecimal((decimal)(object)value, endianness); return; }
throw new NotSupportedException($"不支持的类型: {type.Name}");
}
#endregion
/// <summary>
/// 将流内容转换为字节数组
/// </summary>
public byte[] ToByteArray()
{
byte[] result = new byte[_length];
Array.Copy(_buffer, result, _length);
return result;
}
/// <summary>
/// 辅助方法:判断是否需要反转字节顺序
/// </summary>
private bool NeedReverse(Endianness endianness)
{
return (endianness == Endianness.BigEndian && BitConverter.IsLittleEndian) ||
(endianness == Endianness.LittleEndian && !BitConverter.IsLittleEndian);
}
}
/// <summary>
/// 字节序枚举
/// </summary>
public enum Endianness
{
LittleEndian, // 小端字节序
BigEndian // 大端字节序
}
}

View File

@@ -1,94 +1,94 @@
using NLog; //using NLog;
using NLog.Config; //using NLog.Config;
using System; using System;
using .Utility.Extension; using .Utility.Extension;
namespace .Utility.Logs namespace .Utility.Logs
{ {
public class LogHelper //public class LogHelper
{ //{
private readonly Logger _logger = LogManager.GetCurrentClassLogger(); // private readonly Logger _logger = LogManager.GetCurrentClassLogger();
private static LogHelper _obj; // private static LogHelper _obj;
private LogHelper() // private LogHelper()
{ // {
LogManager.Configuration = new XmlLoggingConfiguration(MyEnvironment.Root("/Configs/NLog.config")); // LogManager.Configuration = new XmlLoggingConfiguration(MyEnvironment.Root("/Configs/NLog.config"));
} // }
public static LogHelper Instance => _obj ?? (new LogHelper()); // public static LogHelper Instance => _obj ?? (new LogHelper());
#region Debug // #region Debug,调
public void Debug(string msg) // public void Debug(string msg)
{ // {
_logger.Debug(msg); // _logger.Debug(msg);
} // }
public void Debug(string msg, Exception err) // public void Debug(string msg, Exception err)
{ // {
_logger.Debug(err, msg); // _logger.Debug(err, msg);
} // }
#endregion // #endregion
#region Info // #region Info,信
public void Info(string msg) // public void Info(string msg)
{ // {
_logger.Info(msg); // _logger.Info(msg);
} // }
public void Info(string msg, Exception err) // public void Info(string msg, Exception err)
{ // {
_logger.Info(err, msg); // _logger.Info(err, msg);
} // }
#endregion // #endregion
#region Warn // #region Warn,警
public void Warn(string msg) // public void Warn(string msg)
{ // {
_logger.Warn(msg); // _logger.Warn(msg);
} // }
public void Warn(string msg, Exception err) // public void Warn(string msg, Exception err)
{ // {
_logger.Warn(err, msg); // _logger.Warn(err, msg);
} // }
#endregion // #endregion
#region Trace // #region Trace,追
public void Trace(string msg) // public void Trace(string msg)
{ // {
_logger.Trace(msg); // _logger.Trace(msg);
} // }
public void Trace(string msg, Exception err) // public void Trace(string msg, Exception err)
{ // {
_logger.Trace(err, msg); // _logger.Trace(err, msg);
} // }
#endregion // #endregion
#region Error // #region Error,错
public void Error(string msg) // public void Error(string msg)
{ // {
_logger.Error(msg); // _logger.Error(msg);
} // }
public void Error(string msg, Exception err) // public void Error(string msg, Exception err)
{ // {
_logger.Error(err, msg); // _logger.Error(err, msg);
} // }
#endregion // #endregion
#region Fatal, // #region Fatal,致命错
public void Fatal(string msg) // public void Fatal(string msg)
{ // {
_logger.Fatal(msg); // _logger.Fatal(msg);
} // }
public void Fatal(string msg, Exception err) // public void Fatal(string msg, Exception err)
{ // {
_logger.Fatal(err, msg); // _logger.Fatal(err, msg);
} // }
#endregion // #endregion
} //}
} }

View File

@@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace .Utility.Web
{
public class WithExtensionMultipartFormDataStreamProvider : MultipartFormDataStreamProvider
{
public string guid { get; set; }
public string OriginalName { get; set; }
public string Ext { get; set; }
public WithExtensionMultipartFormDataStreamProvider(string rootPath, string guidStr) : base(rootPath)
{
guid = guidStr;
}
public override string GetLocalFileName(System.Net.Http.Headers.HttpContentHeaders headers)
{
OriginalName = !string.IsNullOrWhiteSpace(headers.ContentDisposition.FileName) ? GetValidFileName(headers.ContentDisposition.FileName) : "";
Ext = !string.IsNullOrWhiteSpace(OriginalName) ? Path.GetExtension(GetValidFileName(OriginalName)) : "";
return guid + Ext;
}
private string GetValidFileName(string filePath)
{
char[] invalids = System.IO.Path.GetInvalidFileNameChars();
return string.Join("_", filePath.Split(invalids, StringSplitOptions.RemoveEmptyEntries)).TrimEnd('.');
}
}
}

View File

@@ -1,19 +1,20 @@
using Nancy; using System;
using Nancy.Hosting.Self;
using Nancy.Json;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Forms; using System.Windows.Forms;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using .Base; using .Base;
using .Models;
using .Utility; using .Utility;
using .Utility.Core;
using .Utility.Extension; using .Utility.Extension;
namespace .ViewModels namespace .ViewModels
@@ -43,15 +44,18 @@ namespace 电子展板.ViewModels
this.window.Top = (int)(Screen.AllScreens[screenIndex].Bounds.Top / GetDpiScaleX()); this.window.Top = (int)(Screen.AllScreens[screenIndex].Bounds.Top / GetDpiScaleX());
this.window.Width = (int)(Screen.AllScreens[screenIndex].Bounds.Width / GetDpiScaleX()); this.window.Width = (int)(Screen.AllScreens[screenIndex].Bounds.Width / GetDpiScaleX());
this.window.Height = (int)(Screen.AllScreens[screenIndex].Bounds.Height / GetDpiScaleX()); this.window.Height = (int)(Screen.AllScreens[screenIndex].Bounds.Height / GetDpiScaleX());
GlobalVariable.WebServer = new NancyHost(new Uri("http://localhost:80"));
GlobalVariable.WebServer.Start(); WebServer.Start();
//GlobalVariable.WebServer = new NancyHost(new Uri("http://localhost:80"));
//GlobalVariable.WebServer.Start();
} }
private void WindowClosing(CancelEventArgs args) private void WindowClosing(CancelEventArgs args)
{ {
GlobalVariable.WebServer?.Stop(); WebServer.Stop();
GlobalVariable.WebServer?.Dispose(); //GlobalVariable.WebServer?.Stop();
GlobalVariable.WebServer = null; //GlobalVariable.WebServer?.Dispose();
//GlobalVariable.WebServer = null;
Environment.Exit(0); Environment.Exit(0);
} }
public double GetDpiScaleX() public double GetDpiScaleX()
@@ -70,62 +74,32 @@ namespace 电子展板.ViewModels
private void InitImage() private void InitImage()
{ {
try Image1 = GetImage(Config.CPCMember1Path);
{ Image2 = GetImage(Config.CPCMember2Path);
BitmapImage image1 = new BitmapImage(); Image3 = GetImage(Config.CPCMember3Path);
image1.BeginInit(); Image4 = GetImage(Config.CPCMember4Path);
image1.CacheOption = BitmapCacheOption.OnLoad; }
image1.StreamSource = new MemoryStream(File.ReadAllBytes(MyEnvironment.Root(Config.CPCMember1Path)));
image1.EndInit();
image1.Freeze();
Image1 = image1;
}
catch (Exception ex)
{
Image1 = null;
}
try
{
BitmapImage image2 = new BitmapImage();
image2.BeginInit();
image2.CacheOption = BitmapCacheOption.OnLoad;
image2.StreamSource = new MemoryStream(File.ReadAllBytes(MyEnvironment.Root(Config.CPCMember2Path)));
image2.EndInit();
image2.Freeze();
Image2 = image2;
}
catch (Exception ex)
{
Image2 = null;
} private ImageSource GetImage(string path)
{
try try
{ {
BitmapImage image3 = new BitmapImage(); if (path.IsNullOrEmpty())
image3.BeginInit(); return null;
image3.CacheOption = BitmapCacheOption.OnLoad; UploadFiles uploadFiles = GlobalVariable.Config.FileUploadList.FirstOrDefault(x => path.EndsWith(x.Name));
image3.StreamSource = new MemoryStream(File.ReadAllBytes(MyEnvironment.Root(Config.CPCMember3Path))); if (uploadFiles == null)
image3.EndInit(); return null;
image3.Freeze(); BitmapImage image = new BitmapImage();
Image3 = image3; image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
image.StreamSource = new ByteArrayStream(uploadFiles.Bin);
image.EndInit();
image.Freeze();
return image;
} }
catch (Exception ex) catch (Exception ex)
{ {
Image3 = null; return null;
}
try
{
BitmapImage image4 = new BitmapImage();
image4.BeginInit();
image4.CacheOption = BitmapCacheOption.OnLoad;
image4.StreamSource = new MemoryStream(File.ReadAllBytes(MyEnvironment.Root(Config.CPCMember4Path)));
image4.EndInit();
image4.Freeze();
Image4 = image4;
}
catch (Exception ex)
{
Image4 = null;
} }
} }
} }

View File

@@ -6,6 +6,7 @@ using Swagger.ObjectModel;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.IO.Pipes;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using .Base; using .Base;
@@ -100,7 +101,11 @@ namespace 电子展板.WebModule
private object GetUploadFiles(string id) private object GetUploadFiles(string id)
{ {
string contentType = MimeTypes.GetMimeType(id); string contentType = MimeTypes.GetMimeType(id);
return Response.AsFile(MyEnvironment.Root("/Upload/" + id), contentType); //return Response.AsFile(MyEnvironment.Root("/Upload/" + id), contentType);
UploadFiles uploadFiles = GlobalVariable.Config.FileUploadList.FirstOrDefault(x => x.Name == id);
if (uploadFiles == null)
return null;
return Response.FromStream(new MemoryStream(uploadFiles.Bin), contentType);
} }
/// <summary> /// <summary>
@@ -120,14 +125,21 @@ namespace 电子展板.WebModule
{ {
Directory.CreateDirectory(uploadPath); Directory.CreateDirectory(uploadPath);
} }
string ext = Path.GetExtension(file.Name); string ext = Path.GetExtension(file.Name);
string fileName = UUID.StrSnowId + ext; string fileName = UUID.StrSnowId + ext;
var filePath = uploadPath + fileName;
using (FileStream fileStream = new FileStream(filePath, FileMode.Create)) //var filePath = uploadPath + fileName;
{ //using (FileStream fileStream = new FileStream(filePath, FileMode.Create))
file.Value.CopyTo(fileStream); //{
} // file.Value.CopyTo(fileStream);
//}
ByteArrayStream stream = new ByteArrayStream();
file.Value.CopyTo(stream);
byte[] data = stream.ToByteArray();
GlobalVariable.Config.FileUploadList.Add(new UploadFiles { Name = fileName, Bin = data });
GlobalVariable.SaveConfig();
RetValue<string> result = new RetValue<string> { state = 1, message = "上传成功", data = $"/upload/{fileName}" }; RetValue<string> result = new RetValue<string> { state = 1, message = "上传成功", data = $"/upload/{fileName}" };
return Response.AsJson(result); return Response.AsJson(result);
} }
@@ -140,11 +152,14 @@ namespace 电子展板.WebModule
[Route(Tags = new[] { "保存配置" })] [Route(Tags = new[] { "保存配置" })]
private object SaveConfig([RouteParam(ParamIn = ParameterIn.Body, Name = "parms", Description = "保存参数", Required = true)] MyConfig config) private object SaveConfig([RouteParam(ParamIn = ParameterIn.Body, Name = "parms", Description = "保存参数", Required = true)] MyConfig config)
{ {
LogHelper.Instance.Info($"用户保存了配置:{JsonHelper.ToJson(config)}");
//保存 //保存
PropertyInfo[] propertyInfos = typeof(MyConfig).GetProperties(); PropertyInfo[] propertyInfos = typeof(MyConfig).GetProperties();
foreach (PropertyInfo propertyInfo in propertyInfos) foreach (PropertyInfo propertyInfo in propertyInfos)
{ {
if (propertyInfo.Name == "FileUploadList")
{
continue;
}
object value = propertyInfo.GetValue(config); object value = propertyInfo.GetValue(config);
propertyInfo.SetValue(GlobalVariable.Config, value); propertyInfo.SetValue(GlobalVariable.Config, value);
} }

View File

@@ -0,0 +1,182 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Reflection;
using System.Text;
using System.Web;
using System.Web.Http;
using .Base;
using .Models;
using .Utility;
using .Utility.Core;
using .Utility.Other;
using .Utility.Web;
using static System.Net.Mime.MediaTypeNames;
namespace .WebModule
{
public class IndexController : ApiController
{
/// 主界面
/// </summary>
/// <returns></returns>
[HttpGet, Route(""), Route("index.html")]
public ActionResult Index()
{
return Resouce("/Views/Index.html", "text/html");
}
/// <summary>
/// 获得配置信息
/// </summary>
/// <returns></returns>
[HttpGet, Route("getConfig")]
public ActionResult GetConfig()
{
return Json(GlobalVariable.Config);
}
/// <summary>
/// 上传图片。
/// </summary>
/// <returns></returns>
[HttpPost, Route("uploadImage")]
public ActionResult UploadImage()
{
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string tempPath = Path.GetTempPath();
var provider = new WithExtensionMultipartFormDataStreamProvider(tempPath, UUID.StrSnowId);
var fileData = Request.Content.ReadAsMultipartAsync(provider).Result;
if (fileData.FileData.Count == 0)
{
return Error();
}
var file = fileData.FileData[0];
byte[] data = null;
using (ByteArrayStream byteArrayStream = new ByteArrayStream())
{
using (var stream = System.IO.File.OpenRead(file.LocalFileName))
{
stream.CopyTo(byteArrayStream);
}
System.IO.File.Delete(file.LocalFileName);
data = byteArrayStream.ToByteArray();
}
string filename = Path.GetFileName(file.LocalFileName);
GlobalVariable.Config.FileUploadList.Add(new UploadFiles { Name = filename, Bin = data });
GlobalVariable.SaveConfig();
string virtualPath = "/upload/" + filename;
return Success("上传成功", virtualPath);
}
/// <summary>
/// 图形显示
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpGet, Route("upload/{id}")]
public ActionResult GetUploadFile([FromUri] string id)
{
string contentType = System.Web.MimeMapping.GetMimeMapping(id);
UploadFiles uploadFiles = GlobalVariable.Config.FileUploadList.FirstOrDefault(x => x.Name == id);
if (uploadFiles == null)
return null;
return File(uploadFiles.Bin, id, contentType);
}
/// <summary>
/// 保存配置文件
/// </summary>
/// <param name="config"></param>
/// <returns></returns>
[HttpPost, Route("save")]
public ActionResult Save([FromBody] MyConfig config)
{
//保存
PropertyInfo[] propertyInfos = typeof(MyConfig).GetProperties();
foreach (PropertyInfo propertyInfo in propertyInfos)
{
if (propertyInfo.Name == "FileUploadList")
{
continue;
}
object value = propertyInfo.GetValue(config);
propertyInfo.SetValue(GlobalVariable.Config, value);
}
GlobalVariable.SaveConfig();
//保存并修改界面
EventBus.Instance.Publish("save", "");
return Success();
}
private ActionResult File(byte[] bytes, string name, string contentType)
{
ActionResult response = new ActionResult(HttpStatusCode.OK);
response.Content = new StreamContent(new MemoryStream(bytes));
response.Content.Headers.ContentType = new MediaTypeHeaderValue(contentType);
response.Content.Headers.ContentLength = bytes.Length;
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = HttpUtility.UrlEncode(name)
};
response.Headers.Add("Access-Control-Expose-Headers", "FileName");
response.Headers.Add("FileName", HttpUtility.UrlEncode(name));
return response;
}
private ActionResult Json(object obj)
{
return new ActionResult { Content = new StringContent(obj.ToJson(), Encoding.UTF8, "application/json") };
}
public ActionResult Resouce(string viewName, string contentType)
{
string packUri = $"pack://application:,,,/Assets{viewName}";
byte[] bytes = null;
using (Stream stream = System.Windows.Application.GetResourceStream(new Uri(packUri, UriKind.RelativeOrAbsolute)).Stream)
{
bytes = new byte[stream.Length];
stream.Read(bytes, 0, bytes.Length);
}
ActionResult response = new ActionResult(HttpStatusCode.OK);
response.Content = new ByteArrayContent(bytes);
response.Content.Headers.ContentType = new MediaTypeHeaderValue(contentType);
response.Content.Headers.ContentLength = bytes.Length;
return response;
}
protected ActionResult Success(string message = "恭喜您,操作成功。", object data = null)
{
return Json(new { state = 1, message, data });
}
protected ActionResult Error(string message = "对不起,操作失败。", object data = null)
{
return Json(new { state = 2, message, data });
}
}
public class ActionResult : System.Net.Http.HttpResponseMessage
{
public ActionResult() : base(HttpStatusCode.OK)
{
}
public ActionResult(HttpStatusCode statusCode) : base(statusCode)
{
}
}
}

120
电子展板/WebServer.cs Normal file
View File

@@ -0,0 +1,120 @@
using Microsoft.Owin;
using Microsoft.Owin.Hosting;
using Nancy.Hosting.Self;
using Owin;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http.Formatting;
using System.Text;
using System.Threading.Tasks;
using System.Web.Http;
using static System.Net.Mime.MediaTypeNames;
namespace
{
public class WebServer
{
private static bool UseNancy = false;
private static NancyHost _host;
private static IDisposable host;
public static void Start()
{
if (UseNancy)
{
_host = new NancyHost(new Uri("http://localhost:80"));
_host.Start();
}
else
{
StartOptions startOptions = new StartOptions();
startOptions.Urls.Add($"http://*:80/");
host = WebApp.Start<Startup>(startOptions);
}
}
public static void Stop()
{
if (_host != null)
{
_host.Stop();
_host.Dispose();
_host = null;
}
if (host != null)
{
host.Dispose();
host = null;
}
}
}
/// <summary>
/// Web启动类
/// </summary>
public class Startup
{
private HttpConfiguration _config;
/// <summary>
/// 配置
/// </summary>
/// <param name="app"></param>
/// <param name="env"></param>
public void Configuration(IAppBuilder app)
{
_config = new HttpConfiguration();
_config.MapHttpAttributeRoutes();
_config.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
_config.Formatters.JsonFormatter.MediaTypeMappings.Add(new QueryStringMapping("datatype", "json", "application/json"));
//全局拦截
app.Use<ResouceStaticRoute>("/static", "/Assets");
app.UseWebApi(_config);
}
}
public class ResouceStaticRoute : OwinMiddleware
{
private string route;
private string resources;
public ResouceStaticRoute(OwinMiddleware next, string route, string resources) : base(next)
{
this.route = route;
this.resources = resources;
}
public override async Task Invoke(IOwinContext context)
{
try
{
string method = context.Request.Method;//GET POST
string path = context.Request.Path.ToString();
if (method.ToUpper() == "GET" && path.StartsWith(route))
{
string resourePath = path.Replace(route, "");
string packUri = $"pack://application:,,,{resources}{resourePath}";
byte[] bytes = null;
using (Stream stream = System.Windows.Application.GetResourceStream(new Uri(packUri, UriKind.RelativeOrAbsolute)).Stream)
{
bytes = new byte[stream.Length];
stream.Read(bytes, 0, bytes.Length);
}
context.Response.ContentType = System.Web.MimeMapping.GetMimeMapping(path);
context.Response.Write(bytes, 0, bytes.Length);
await Task.FromResult(0);
}
await Next.Invoke(context);
}
catch (InvalidCastException ex)
{
await Next.Invoke(context);
}
catch (Exception ex)
{
await Next.Invoke(context);
}
}
}
}

View File

@@ -11,19 +11,25 @@
<ItemGroup> <ItemGroup>
<Content Include="favicon.ico" /> <Content Include="favicon.ico" />
<Resource Include="Assets\**" /> <Resource Include="Assets\**" />
<Content Include="..\Configs\*" Link="Configs\%(Filename)%(Extension)"> <!--<Content Include="..\Configs\*" Link="%(Filename)%(Extension)">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>-->
<Content Include="..\Configs\Config.json" Link="%(Filename)%(Extension)">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System.Windows.Forms" /> <Reference Include="System.Windows.Forms" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Costura.Fody" Version="6.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<!-- JSON框架 --> <!-- JSON框架 -->
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
<!-- 日志框架 --> <!-- 日志框架 -->
<PackageReference Include="NLog" Version="6.0.2" /> <!--<PackageReference Include="NLog" Version="6.0.2" />-->
<!-- WEB 自宿主 --> <!-- WEB 自宿主 -->
<PackageReference Include="ZJW.NancySwagger" Version="2.0.1" /> <PackageReference Include="ZJW.NancySwagger" Version="2.0.1" />
<PackageReference Include="Nancy.Hosting.Self" Version="2.0.0" /> <PackageReference Include="Nancy.Hosting.Self" Version="2.0.0" />
@@ -31,10 +37,17 @@
<PackageReference Include="HandyControl" Version="3.5.1" /> <PackageReference Include="HandyControl" Version="3.5.1" />
<PackageReference Include="PropertyChanged.Fody" Version="4.1.0" /> <PackageReference Include="PropertyChanged.Fody" Version="4.1.0" />
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.135" /> <PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.135" />
</ItemGroup>
<ItemGroup> <!-- WEB 自宿主 -->
<Content Include="Upload\0.jpg"> <PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="9.0.9" />
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <PackageReference Include="Microsoft.AspNet.WebApi.Owin" version="5.3.0" />
</Content> <PackageReference Include="Microsoft.AspNet.WebApi.Core" Version="5.3.0" />
<PackageReference Include="Microsoft.Owin" Version="4.2.3" />
<PackageReference Include="Microsoft.Owin.Host.SystemWeb" Version="4.2.3" />
<PackageReference Include="Microsoft.AspNet.WebApi.OwinSelfHost" Version="5.3.0" />
<PackageReference Include="Microsoft.AspNet.Identity.Owin" Version="2.2.4" />
<PackageReference Include="Swashbuckle.Core" version="5.6.0" />
<PackageReference Include="Beginor.Owin.StaticFile" Version="0.3.1" />
<PackageReference Include="Microsoft.AspNet.Mvc" Version="5.3.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>