using System.IO; namespace Top.Api.Util { /// /// 文件元数据。 /// 可以使用以下几种构造方法: /// 本地路径:new FileItem("C:/temp.jpg"); /// 本地文件:new FileItem(new FileInfo("C:/temp.jpg")); /// 字节数组:new FileItem("abc.jpg", bytes); /// 输入流:new FileItem("abc.jpg", stream); /// public class FileItem { private Contract contract; /// /// 基于本地文件的构造器。 /// /// 本地文件 public FileItem(FileInfo fileInfo) { this.contract = new LocalContract(fileInfo); } /// /// 基于本地文件全路径的构造器。 /// /// 本地文件全路径 public FileItem(string filePath) : this(new FileInfo(filePath)) { } /// /// 基于文件名和字节数组的构造器。 /// /// 文件名称(服务端持久化字节数组到磁盘时的文件名) /// 文件字节数组 public FileItem(string fileName, byte[] content) : this(fileName, content, null) { } /// /// 基于文件名、字节数组和媒体类型的构造器。 /// /// 文件名(服务端持久化字节数组到磁盘时的文件名) /// 文件字字节数组 /// 媒体类型 public FileItem(string fileName, byte[] content, string mimeType) { this.contract = new ByteArrayContract(fileName, content, mimeType); } /// /// 基于文件名和输入流的构造器。 /// /// 文件名称(服务端持久化输入流到磁盘时的文件名) /// 文件输入流 public FileItem(string fileName, Stream stream) : this(fileName, stream, null) { } /// /// 基于文件名、输入流和媒体类型的构造器。 /// /// 文件名(服务端持久化输入流到磁盘时的文件名) /// 文件输入流 /// 媒体类型 public FileItem(string fileName, Stream stream, string mimeType) { this.contract = new StreamContract(fileName, stream, mimeType); } public bool IsValid() { return this.contract.IsValid(); } public long GetFileLength() { return this.contract.GetFileLength(); } public string GetFileName() { return this.contract.GetFileName(); } public string GetMimeType() { return this.contract.GetMimeType(); } public void Write(Stream output) { this.contract.Write(output); } } internal interface Contract { bool IsValid(); string GetFileName(); string GetMimeType(); long GetFileLength(); void Write(Stream output); } internal class LocalContract : Contract { private FileInfo fileInfo; public LocalContract(FileInfo fileInfo) { this.fileInfo = fileInfo; } public long GetFileLength() { return this.fileInfo.Length; } public string GetFileName() { return this.fileInfo.Name; } public string GetMimeType() { return Constants.CTYPE_DEFAULT; } public bool IsValid() { return this.fileInfo != null && this.fileInfo.Exists; } public void Write(Stream output) { using (BufferedStream bfs = new BufferedStream(this.fileInfo.OpenRead())) { int n = 0; byte[] buffer = new byte[Constants.READ_BUFFER_SIZE]; while ((n = bfs.Read(buffer, 0, buffer.Length)) > 0) { output.Write(buffer, 0, n); } } } } internal class ByteArrayContract : Contract { private string fileName; private byte[] content; private string mimeType; public ByteArrayContract(string fileName, byte[] content, string mimeType) { this.fileName = fileName; this.content = content; this.mimeType = mimeType; } public bool IsValid() { return this.content != null && this.fileName != null; } public long GetFileLength() { return this.content.Length; } public string GetFileName() { return this.fileName; } public string GetMimeType() { if (string.IsNullOrEmpty(this.mimeType)) { return Constants.CTYPE_DEFAULT; } else { return this.mimeType; } } public void Write(Stream output) { output.Write(this.content, 0, this.content.Length); } } internal class StreamContract : Contract { private string fileName; private Stream stream; private string mimeType; public StreamContract(string fileName, Stream stream, string mimeType) { this.fileName = fileName; this.stream = stream; this.mimeType = mimeType; } public long GetFileLength() { return 0L; } public string GetFileName() { return this.fileName; } public string GetMimeType() { if (string.IsNullOrEmpty(mimeType)) { return Constants.CTYPE_DEFAULT; } else { return this.mimeType; } } public bool IsValid() { return this.stream != null && this.fileName != null; } public void Write(Stream output) { using (this.stream) { int n = 0; byte[] buffer = new byte[Constants.READ_BUFFER_SIZE]; while ((n = this.stream.Read(buffer, 0, buffer.Length)) > 0) { output.Write(buffer, 0, n); } } } } }