123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353 |
- using System;
- using System.IO;
- using COSXML.Log;
- namespace COSXML.Network
- {
- public sealed class ResponseBody
- {
- private const int SEGMENT_SIZE = 4096;
- private long contentLength = -1L;
- private string contentType;
- private COSXML.Callback.OnProgressCallback progressCallback;
- private COSXML.Callback.OnParseStream parseStream;
- private string filePath;
- private long fileOffset;
- private FileStream fileStream;
- private bool isDownload = false;
- private MemoryStream memoryStream;
- public long ContentLength
- {
- get
- {
- return contentLength;
- }
- set { contentLength = value; }
- }
- public string ContentType
- {
- get
- {
- return contentType;
- }
- set { contentType = value; }
- }
- public COSXML.Callback.OnProgressCallback ProgressCallback
- {
- get
- {
- return progressCallback;
- }
- set { progressCallback = value; }
- }
- public COSXML.Callback.OnParseStream ParseStream
- {
- get
- {
- return parseStream;
- }
- set { parseStream = value; }
- }
- public string rawContentBodyString { get; private set; }
- public ResponseBody()
- {
- }
- public ResponseBody(string filePath, long fileOffset)
- {
- this.filePath = filePath;
- this.fileOffset = fileOffset;
- this.isDownload = true;
- }
- /// <summary>
- /// handle cos response
- /// </summary>
- /// <param name="inputStream"></param>
- /// <exception cref="CosServerException"> throw CosServerException </exception>
- /// <exception cref="Exception">throw Exception</exception>
- public void HandleResponseBody(Stream inputStream)
- {
- try
- {
- if (isDownload)
- {
- if (File.Exists(filePath) && new FileInfo(filePath).Length > fileOffset)
- {
- // 写脏文件了,直接 Truncate
- fileStream = new FileStream(filePath, FileMode.Truncate, FileAccess.Write);
- }
- else
- {
- // 正常文件或者追加写场景,直接写入
- fileStream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write);
- }
- fileStream.Seek(fileOffset, SeekOrigin.Begin);
- byte[] buffer = new byte[SEGMENT_SIZE];
- int recvLen = 0;
- long completed = recvLen;
- while ((recvLen = inputStream.Read(buffer, 0, buffer.Length)) != 0)
- {
- fileStream.Write(buffer, 0, recvLen);
- if (progressCallback != null)
- {
- completed += recvLen;
- progressCallback(completed, contentLength);
- }
- }
- fileStream.Flush();
- }
- else
- {
- if ("application/xml".Equals(contentType, StringComparison.OrdinalIgnoreCase) &&
- contentLength > 0 && contentLength < 10 * 1000)
- {
- // save raw content
- memoryStream = new MemoryStream((int)contentLength);
-
- //inputStream.CopyTo(memoryStream);
- byte[] buffer = new byte[10 * 1000];
- int count;
- while ((count = inputStream.Read(buffer, 0, buffer.Length)) != 0)
- {
- memoryStream.Write(buffer, 0, count);
- }
- rawContentBodyString = System.Text.Encoding.UTF8.GetString(memoryStream.ToArray());
- memoryStream.Seek(0, SeekOrigin.Begin);
- inputStream = memoryStream;
- }
- if (parseStream != null)
- {
- parseStream(inputStream, contentType, contentLength);
- }
- }
- }
- catch (Exception ex)
- {
- QLog.Error("ResponseBody", ex.Message, ex);
- throw;
- }
-
- finally
- {
- if (inputStream != null)
- {
- inputStream.Close();
- inputStream.Dispose();
- }
- if (fileStream != null)
- {
- fileStream.Close();
- fileStream.Dispose();
- }
- //if (memoryStream != null) memoryStream.Close();
- }
- }
- public void StartHandleResponseBody(Stream inputStream, EndResponseBody endResponseBody)
- {
- ResponseBodyState responseBodyState = new ResponseBodyState();
- responseBodyState.inputStream = inputStream;
- responseBodyState.endResponseBody = endResponseBody;
- responseBodyState.completed = 0L;
- try
- {
- int count = (int)((contentLength > SEGMENT_SIZE || contentLength <= 0) ? SEGMENT_SIZE : contentLength);
- byte[] buffer = new byte[count];
- responseBodyState.buffer = buffer;
- if (isDownload)
- {
- if (File.Exists(filePath) && new FileInfo(filePath).Length > fileOffset)
- {
- // 写脏文件了,直接 Truncate
- fileStream = new FileStream(filePath, FileMode.Truncate, FileAccess.Write);
- }
- else
- {
- // 正常文件或者追加写场景,直接写入
- fileStream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write);
- }
- fileStream.Seek(fileOffset, SeekOrigin.Begin);
- responseBodyState.inputStream.BeginRead(responseBodyState.buffer, 0, responseBodyState.buffer.Length, AsyncStreamCallback, responseBodyState);
- }
- else
- {
- memoryStream = new MemoryStream(count);
- responseBodyState.buffer = buffer;
- responseBodyState.inputStream.BeginRead(responseBodyState.buffer, 0, responseBodyState.buffer.Length, AsyncStreamCallback, responseBodyState);
- }
- }
- catch (Exception ex)
- {
- if (fileStream != null)
- {
- fileStream.Close();
- fileStream.Dispose();
- }
- if (memoryStream != null)
- {
- memoryStream.Close();
- memoryStream.Dispose();
- }
- responseBodyState.endResponseBody(false, ex);
- responseBodyState.Clear();
- QLog.Error("ResponseBody", ex.Message, ex);
- }
- }
- private void AsyncStreamCallback(IAsyncResult ar)
- {
- ResponseBodyState responseBodyState = ar.AsyncState as ResponseBodyState;
- Stream inputStream = responseBodyState.inputStream;
- try
- {
- int recvLen = inputStream.EndRead(ar);
- responseBodyState.completed += recvLen;
- if (recvLen > 0)
- {
- if (isDownload)
- {
- fileStream.Write(responseBodyState.buffer, 0, recvLen);
- if (progressCallback != null)
- {
- progressCallback(responseBodyState.completed, contentLength);
- }
- }
- else
- {
- memoryStream.Write(responseBodyState.buffer, 0, recvLen);
- }
- inputStream.BeginRead(responseBodyState.buffer, 0, responseBodyState.buffer.Length, AsyncStreamCallback, responseBodyState);
- }
- else if (recvLen == 0)
- {
- if (isDownload)
- {
- fileStream.Flush();
- }
- else
- {
- if ("application/xml".Equals(contentType, StringComparison.OrdinalIgnoreCase) &&
- memoryStream.Length > 0 && memoryStream.Length < 10 * 1000)
- {
- memoryStream.Seek(0, SeekOrigin.Begin);
- rawContentBodyString = System.Text.Encoding.UTF8.GetString(memoryStream.ToArray());
- }
- memoryStream.Seek(0, SeekOrigin.Begin);
- parseStream(memoryStream, contentType, responseBodyState.completed);
- }
- if (fileStream != null)
- {
- fileStream.Close();
- fileStream.Dispose();
- }
- if (memoryStream != null)
- {
- memoryStream.Close();
- memoryStream.Dispose();
- }
- responseBodyState.endResponseBody(true, null);
- responseBodyState.Clear();
- }
- }
- catch (Exception ex)
- {
- if (fileStream != null)
- {
- fileStream.Close();
- fileStream.Dispose();
- }
- if (memoryStream != null)
- {
- memoryStream.Close();
- memoryStream.Dispose();
- }
- responseBodyState.endResponseBody(false, ex);
- responseBodyState.Clear();
- QLog.Error("ResponseBody", ex.Message, ex);
- }
- }
- }
- public delegate void EndResponseBody(bool isSuccess, Exception ex);
- public class ResponseBodyState
- {
- public Stream inputStream;
- public byte[] buffer;
- public long completed;
- public EndResponseBody endResponseBody;
- public void Clear()
- {
- if (inputStream != null)
- {
- inputStream.Close();
- }
- if (buffer != null)
- {
- buffer = null;
- }
- }
- }
- }
|