/// <summary> /// virtualPath는 무조건 상대경로로 인식함. /// ServerContext.FileRootPath + virtualPath /// example : /image/abc.jpg -> image/abc.jpg /// </summary> public string GetStoragePath(ServerContext context, string virtualPath) { string storagePath = GetStoragePathInternal(context, virtualPath); // change as Windows path if (Path.DirectorySeparatorChar == '\\') { storagePath = Bingle.Common.StringUtil.ReverseSlash(storagePath, '/'); } return storagePath; }
/// <summary> /// 현재는 session에 저장되어 있는 단일 stream으로 하기 때문에 /// 차후 추가 connection을 열어서 하는 방법으로 수정해야함. /// </summary> /// <param name="serverContext">BingleServer.ServerContext</param> /// <param name="fileContext">session.FileContext</param> /// <param name="bingleSession"></param> /// <returns></returns> public bool SendFile(ServerContext serverContext, string fileName, BingleSession session) { int bufLen = 1024 * 4; byte[] buffer = new byte[bufLen]; int read = 0; byte fragmented = StatusData.FRAGMENTED; byte lastMsg = StatusData.NOT_LASTMSG; int sequence = 0; FileStream fs = null; BingleHeader header = null; BingleProtocol<BingleHeader, BodySTOR> protocol = null; try { string filePath = GetStoragePath(serverContext, fileName); // (test), serverContext와 각종 데이터와 조합된 이름을 사용해야함 //string filePath = fileContext.SendFilePath; Console.WriteLine("Send File Path - {0}", filePath); fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, bufLen); while ((read = fs.Read(buffer, 0, bufLen)) > 0) { if (read < bufLen) { if (sequence > 0) { fragmented = StatusData.FRAGMENTED; } else { fragmented = StatusData.NOT_FRAGMENTED; } lastMsg = StatusData.LASTMSG; } header = new BingleHeader(read, fragmented, lastMsg, sequence); protocol = new BingleProtocol<BingleHeader, BodySTOR>( CommandList.STOR, header, new BodySTOR(buffer.CloneRange(0, read))); session.Send(protocol.GetBytes(), 0, protocol.GetSize()); ++sequence; } return true; } catch (IOException e) { AppServer.Logger.Error(e); Console.WriteLine("BingleServiceProvider - Failed to Send file"); return false; } catch (SocketException e) { AppServer.Logger.Error(e); Console.WriteLine("BingleServiceProvider - Data Connection Error"); return false; } finally { if (fs != null) { fs.Close(); fs.Dispose(); fs = null; } } }
/// <summary> /// virtualPath를 상대경로로 변환 후 기준 경로와 병합함. /// </summary> protected virtual string GetStoragePathInternal(ServerContext context, string virtualPath) { virtualPath = virtualPath.TrimStart(Path.DirectorySeparatorChar); return Path.Combine(context.FileRootPath, virtualPath); }
/// <summary> /// 현재는 session에 저장되어 있는 단일 stream으로 하기 때문에 /// 차후 추가 connection을 열어서 하는 방법으로 수정해야함. /// </summary> /// <param name="serverContext"></param> /// <param name="fileContext">session.FileContext</param> /// <param name="bingleProtocol"></param> /// <returns></returns> public bool StoreFile(ServerContext serverContext, string fileName, FileContext fileContext, BingleProtocol bingleProtocol) { int bufLen = 1024 * 4; try { if (fileContext.FileDataStream == null) { // (test), serverContext와 각종 데이터와 조합된 이름을 사용해야함 //string filePath = fileName; string filePath = GetStoragePath(serverContext, fileName); Console.WriteLine("Store File Path - {0}", filePath); if (File.Exists(filePath)) { File.Delete(filePath); } fileContext.FileDataStream = new FileStream( filePath, FileMode.CreateNew, FileAccess.Write, FileShare.Write, bufLen); } fileContext.FileDataStream.Write(bingleProtocol.Body, 0, bingleProtocol.Header.BodyLength); fileContext.TotalReadSize += bingleProtocol.Header.BodyLength; if (fileContext.TotalReadSize >= fileContext.FileSize) { /// 임시 - 또 다른 요청이 있을 수 있기 때문에 초기화 해야함. /// connection을 여는 방법을 써야 할 것 같다. if (fileContext.FileDataStream != null) { fileContext.FileDataStream.Close(); fileContext.FileDataStream.Dispose(); fileContext.FileDataStream = null; } } return true; } catch (IOException e) { AppServer.Logger.Error(e); Console.WriteLine("BingleServiceProvider - Store file Error"); return false; } }