using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
namespace Upload
{
public class AdvertisementSource : IDisposable
{
HttpListener httpListener;
bool stopped;
#region 构造和析构
// ==
#region IDisposable
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
int disposedFlag;
~AdvertisementSource()
{
Dispose(false);
}
///<summary>
///释放所占用的资源
///</summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// 获取该对象是否已经被释放
/// </summary>
[System.ComponentModel.Browsable(false)]
public bool IsDisposed
{
get { return disposedFlag != 0; }
}
#endregion
protected virtual void Dispose(bool disposing)
{
if (System.Threading.Interlocked.Increment(ref disposedFlag) != 1) return;
if (disposing)
{
httpListener.Stop();
}
// 在这里编写非托管资源释放代码
}
#endregion
public void Initialize(int port = 8080)
{
try
{
httpListener = new HttpListener();
httpListener.Prefixes.Add($"http://*:{port}/upload/");
httpListener.Start();
httpListener.BeginGetContext(GetHttpContextCallback, null);
}
catch (Exception e)
{
Console.WriteLine($"{port}被占用");
}
}
public void GetHttpContextCallback(IAsyncResult iar)
{
if (stopped) return;
var context = httpListener.EndGetContext(iar);
httpListener.BeginGetContext(GetHttpContextCallback, null);
//string endPoint = context.Request.RemoteEndPoint.ToString();
//int spIndex = endPoint.IndexOf(":");
//endPoint = endPoint.Substring(0, spIndex);
using (HttpListenerResponse response = context.Response)
{
//get 的方式在如下解析即可得到客户端参数及值
// string userName = context.Request.QueryString["userName"];
// string password = context.Request.QueryString["password"];
// string suffix = context.Request.QueryString["suffix"];
// string adType = context.Request.QueryString["adtype"]; // 文字,图片,视频
if (!context.Request.HasEntityBody) // 无数据
{
response.StatusCode = 403;
return;
}
//post 的方式有文件上传的在如下解析即可得到客户端参数及值
HttpListenerRequest request = context.Request;
if (request.ContentType.Length > 20 && string.Compare(request.ContentType.Substring(0, 20), "multipart/form-data;", true) == 0)
{
List<Values> lst = new List<Values>();
Encoding Encoding = request.ContentEncoding;
string[] values = request.ContentType.Split(';').Skip(1).ToArray();
string boundary = string.Join(";", values).Replace("boundary=", "").Trim();
byte[] ChunkBoundary = Encoding.GetBytes("--" + boundary + "\r\n");
byte[] EndBoundary = Encoding.GetBytes("--" + boundary + "--\r\n");
Stream SourceStream = request.InputStream;
var resultStream = new MemoryStream();
bool CanMoveNext = true;
Values data = null;
while (CanMoveNext)
{
byte[] currentChunk = ReadLineAsBytes(SourceStream);
if (!Encoding.GetString(currentChunk).Equals("\r\n"))
resultStream.Write(currentChunk, 0, currentChunk.Length);
if (CompareBytes(ChunkBoundary, currentChunk))
{
byte[] result = new byte[resultStream.Length - ChunkBoundary.Length];
resultStream.Position = 0;
resultStream.Read(result, 0, result.Length);
CanMoveNext = true;
if (result.Length > 0)
data.datas = result;
data = new Values();
lst.Add(data);
resultStream.Dispose();
resultStream = new MemoryStream();
}
else if (Encoding.GetString(currentChunk).Contains("Content-Disposition"))
{
byte[] result = new byte[resultStream.Length - 2];
resultStream.Position = 0;
resultStream.Read(result, 0, result.Length);
var strings = Encoding.GetString(result).Split('=');
data.fileName = strings[strings.Length - 1].Replace("\"","");
resultStream.Dispose();
resultStream = new MemoryStream();
}
else if (Encoding.GetString(currentChunk).Contains("Content-Type"))
{
CanMoveNext = true;
data.type = 1;
resultStream.Dispose();
resultStream = new MemoryStream();
}
else if (CompareBytes(EndBoundary, currentChunk))
{
byte[] result = new byte[resultStream.Length - EndBoundary.Length - 2];
resultStream.Position = 0;
resultStream.Read(result, 0, result.Length);
data.datas = result;
resultStream.Dispose();
CanMoveNext = false;
}
}
foreach (var key in lst)
{
if (key.type == 0)
{
//参数暂不做处理
}
if (key.type == 1)
{
FileStream fs = new FileStream(System.Web.HttpUtility.UrlDecode(key.fileName), FileMode.Create);
fs.Write(key.datas, 0, key.datas.Length);
fs.Close();
fs.Dispose();
}
}
}
response.ContentType = "text/html;charset=utf-8";
try
{
using (System.IO.Stream output = response.OutputStream)
using (StreamWriter writer = new StreamWriter(output, Encoding.UTF8))
writer.WriteLine("接收完成!");
}
catch
{
}
response.Close();
}
}
byte[] ReadLineAsBytes(Stream SourceStream)
{
var resultStream = new MemoryStream();
while (true)
{
int data = SourceStream.ReadByte();
resultStream.WriteByte((byte) data);
if (data == 10)
break;
}
resultStream.Position = 0;
byte[] dataBytes = new byte[resultStream.Length];
resultStream.Read(dataBytes, 0, dataBytes.Length);
return dataBytes;
}
bool CompareBytes(byte[] source, byte[] comparison)
{
int count = source.Length;
if (source.Length != comparison.Length)
return false;
for (int i = 0; i < count; i++)
if (source[i] != comparison[i])
return false;
return true;
}
public class Values
{
public int type = 0; // 0参数,1文件
public string fileName;
public byte[] datas;
}
}
}
目前存在的问题:1、无法上传中文名字的文件