Files

242 lines
8.2 KiB
C#
Raw Permalink Normal View History

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using COSXML.Common;
using COSXML.Log;
/**
* Copyright (c) 2018 Tencent Cloud. All rights reserved.
* 11/28/2018 2:58:22 PM
* bradyxiao
*/
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 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)
{
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 (parseStream != null)
{
parseStream(inputStream, contentType, contentLength);
}
}
}
catch (Exception ex)
{
QLog.E("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)
{
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)
{
responseBodyState.endResponseBody(false, ex);
responseBodyState.Clear();
if (fileStream != null)
{
fileStream.Close();
fileStream.Dispose();
}
if (memoryStream != null)
{
memoryStream.Close();
memoryStream.Dispose();
}
QLog.E("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
{
memoryStream.Seek(0, SeekOrigin.Begin);
parseStream(memoryStream, contentType, responseBodyState.completed);
}
responseBodyState.endResponseBody(true, null);
responseBodyState.Clear();
if (fileStream != null)
{
fileStream.Close();
fileStream.Dispose();
}
if (memoryStream != null)
{
memoryStream.Close();
memoryStream.Dispose();
}
}
}
catch (Exception ex)
{
responseBodyState.endResponseBody(false, ex);
responseBodyState.Clear();
if (fileStream != null)
{
fileStream.Close();
fileStream.Dispose();
}
if (memoryStream != null)
{
memoryStream.Close();
memoryStream.Dispose();
}
QLog.E("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;
}
}
}