Skip to content

Commit

Permalink
fix: getting content from body
Browse files Browse the repository at this point in the history
  • Loading branch information
TheSuunny committed Feb 4, 2024
1 parent 0d4b248 commit 9213081
Show file tree
Hide file tree
Showing 10 changed files with 346 additions and 237 deletions.
119 changes: 111 additions & 8 deletions Content.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

using Fody;

using Microsoft.IO;

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

using Yove.Http.Exceptions;
Expand All @@ -27,7 +30,9 @@ public class Content : IDisposable

#region Internal

internal MemoryStream Stream { get; } = new();
private readonly RecyclableMemoryStreamManager _streamManager = new();

internal RecyclableMemoryStream Stream { get; set; }

#endregion

Expand All @@ -40,10 +45,21 @@ public async Task<string> ReadAsString()
{
if (_response.IsEmpytyBody)
throw new HttpResponseException("Content not found.");
else if (_response.ContentLength.HasValue && _response.ContentLength > int.MaxValue)
throw new HttpResponseException("The data array is too large (Use ToFile).");

RecyclableMemoryStream outputStream = await ReadAsStream() as RecyclableMemoryStream;

MemoryStream outputStream = await _response.GetBodyContent();
if (outputStream.Length > int.MaxValue)
{
outputStream.Dispose();

return _response.CharacterSet.GetString(outputStream.ToArray(), 0, (int)outputStream.Length);
throw new HttpResponseException("The data array is too large (Use ToFile).");
}

byte[] buffer = outputStream.GetBuffer();

return _response.CharacterSet.GetString(buffer, 0, buffer.Length);
}

public async Task<JToken> ReadAsJson()
Expand All @@ -56,19 +72,106 @@ public async Task<JToken> ReadAsJson()
return JToken.Parse(body);
}

public async Task<MemoryStream> ReadAsStream()
public async Task<T> ReadAsJson<T>()
{
if (_response.IsEmpytyBody)
string body = await ReadAsString();

if (string.IsNullOrEmpty(body))
throw new HttpResponseException("Content not found.");

return await _response.GetBodyContent();
return JsonConvert.DeserializeObject<T>(body);
}

public async Task<byte[]> ReadAsBytes()
{
MemoryStream outputStream = await ReadAsStream();
if (_response.IsEmpytyBody)
throw new HttpResponseException("Content not found.");
if (_response.ContentLength.HasValue && _response.ContentLength > int.MaxValue)
throw new HttpResponseException("The data array is too large (Use ToFile).");

RecyclableMemoryStream outputStream = await ReadAsStream() as RecyclableMemoryStream;

if (outputStream.Length > int.MaxValue)
{
outputStream.Dispose();

throw new HttpResponseException("The data array is too large (Use ToFile).");
}

return outputStream.GetBuffer();
}

public async Task<Stream> ReadAsStream()
{
if (_response.IsEmpytyBody)
throw new HttpResponseException("Content not found.");

Stream ??= _streamManager.GetStream();

if (Stream.Length == 0)
{
await foreach (Memory<byte> source in _response.GetBodyContent())
Stream.Write(source.ToArray(), 0, source.Length);
}

Stream.Seek(0, SeekOrigin.Begin);

return Stream;
}

public async Task<string> ToFile(string filepath)
{
if (string.IsNullOrEmpty(filepath))
throw new NullReferenceException("filepath is null or empty.");

string path = Path.GetDirectoryName(filepath);
string filename = Path.GetFileName(filepath);

return await ToFile(path, filename);
}

public async Task<string> ToFile(string localPath, string filename = null)
{
if (_response.IsEmpytyBody)
throw new NullReferenceException("Content not found.");

if (string.IsNullOrEmpty(localPath))
throw new NullReferenceException("Path is null or empty.");

if (filename == null)
{
if (_response.Headers["Content-Disposition"] != null)
{
filename = $"{localPath.TrimEnd('/')}/{HttpUtils.Parser("filename=\"", _response.Headers["Content-Disposition"], "\"")}";
}
else
{
filename = Path.GetFileName(new Uri(_response.Address.AbsoluteUri).LocalPath);

if (string.IsNullOrEmpty(filename))
throw new NullReferenceException("Could not find filename.");
}
}

string outputPath = Path.Join(localPath.TrimEnd('/'), filename);

Stream ??= _streamManager.GetStream();

using FileStream fileStream = new(outputPath, FileMode.OpenOrCreate);

if (Stream.Length == 0)
{
await foreach (Memory<byte> source in _response.GetBodyContent())
await fileStream.WriteAsync(source);
}
else
{
Stream.Seek(0, SeekOrigin.Begin);

await Stream.CopyToAsync(fileStream);
}

return outputStream?.ToArray();
return outputPath;
}

protected virtual void Dispose(bool disposing)
Expand Down
88 changes: 47 additions & 41 deletions Content/MultipartContent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,32 +32,34 @@ public override long ContentLength
{
get
{
if (_elements.Count == 0)
throw new ObjectDisposedException("Content disposed or empty.");

long length = 0;

foreach (Element item in _elements)
if (_elements.Count != 0)
{
length += item.Content.ContentLength;
long length = 0;

if (item.IsFieldFile)
{
length += 72;
length += item.Name.Length;
length += item.Filename.Length;
length += item.Content.ContentType.Length;
}
else
foreach (Element item in _elements)
{
length += 43;
length += item.Name.Length;
length += item.Content.ContentLength;

if (item.IsFieldFile)
{
length += 72;
length += item.Name.Length;
length += item.Filename.Length;
length += item.Content.ContentType.Length;
}
else
{
length += 43;
length += item.Name.Length;
}

length += _boundary.Length + 6;
}

length += _boundary.Length + 6;
return length += _boundary.Length + 6;
}

return length += _boundary.Length + 6;
throw new ObjectDisposedException("Content disposed or empty.");
}
}

Expand Down Expand Up @@ -187,36 +189,40 @@ public void Add(string name, string contentType, FileContent content, string fil

public override void Write(Stream commonStream)
{
if (_elements.Count == 0)
throw new ObjectDisposedException("Content disposed or empty.");

if (commonStream == null)
throw new NullReferenceException("CommonStream is null.");
if (_elements.Count != 0)
{
if (commonStream == null)
throw new NullReferenceException("CommonStream is null.");

byte[] lineBytes = Encoding.ASCII.GetBytes("\r\n");
byte[] boundaryBytes = Encoding.ASCII.GetBytes($"--{_boundary}\r\n");
byte[] lineBytes = Encoding.ASCII.GetBytes("\r\n");
byte[] boundaryBytes = Encoding.ASCII.GetBytes($"--{_boundary}\r\n");

foreach (Element item in _elements)
{
commonStream.Write(boundaryBytes, 0, boundaryBytes.Length);
foreach (Element item in _elements)
{
commonStream.Write(boundaryBytes, 0, boundaryBytes.Length);

string field;
string field;

if (item.IsFieldFile)
field = $"Content-Disposition: form-data; name=\"{item.Name}\"; filename=\"{item.Filename}\"\r\nContent-Type: {item.Content.ContentType}\r\n\r\n";
else
field = $"Content-Disposition: form-data; name=\"{item.Name}\"\r\n\r\n";
if (item.IsFieldFile)
field = $"Content-Disposition: form-data; name=\"{item.Name}\"; filename=\"{item.Filename}\"\r\nContent-Type: {item.Content.ContentType}\r\n\r\n";
else
field = $"Content-Disposition: form-data; name=\"{item.Name}\"\r\n\r\n";

byte[] fieldBytes = Encoding.ASCII.GetBytes(field);
byte[] fieldBytes = Encoding.ASCII.GetBytes(field);

commonStream.Write(fieldBytes, 0, fieldBytes.Length);
item.Content.Write(commonStream);
commonStream.Write(lineBytes, 0, lineBytes.Length);
}
commonStream.Write(fieldBytes, 0, fieldBytes.Length);
item.Content.Write(commonStream);
commonStream.Write(lineBytes, 0, lineBytes.Length);
}

boundaryBytes = Encoding.ASCII.GetBytes($"--{_boundary}--\r\n");
boundaryBytes = Encoding.ASCII.GetBytes($"--{_boundary}--\r\n");

commonStream.Write(boundaryBytes, 0, boundaryBytes.Length);
commonStream.Write(boundaryBytes, 0, boundaryBytes.Length);
}
else
{
throw new ObjectDisposedException("Content disposed or empty.");
}
}

~MultipartContent()
Expand Down
35 changes: 18 additions & 17 deletions Content/StreamContent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@ public override long ContentLength
{
get
{
if (Content == null)
throw new ObjectDisposedException("Content disposed or empty.");

return Content.Length;
return Content == null ? throw new ObjectDisposedException("Content disposed or empty.") : Content.Length;
}
}

Expand All @@ -33,24 +30,28 @@ public StreamContent(Stream content, int bufferSize = 32768)

public override void Write(Stream commonStream)
{
if (Content == null)
throw new ObjectDisposedException("Content disposed or empty.");

if (commonStream == null)
throw new NullReferenceException("Stream is empty.");
if (Content != null)
{
if (commonStream == null)
throw new NullReferenceException("Stream is empty.");

Content.Position = 0;
Content.Position = 0;

byte[] buffer = new byte[BufferSize];
byte[] buffer = new byte[BufferSize];

while (true)
{
int readBytes = Content.Read(buffer, 0, buffer.Length);
while (true)
{
int readBytes = Content.Read(buffer, 0, buffer.Length);

if (readBytes == 0)
break;
if (readBytes == 0)
break;

commonStream.Write(buffer, 0, readBytes);
commonStream.Write(buffer, 0, readBytes);
}
}
else
{
throw new ObjectDisposedException("Content disposed or empty.");
}
}

Expand Down
12 changes: 3 additions & 9 deletions Events/DownloadEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

namespace Yove.Http.Events;

public class DownloadEvent : EventArgs
public class DownloadEvent(long received, long? total) : EventArgs
{
public long Received { get; }
public long? Total { get; }
public long Received { get; } = received;
public long? Total { get; } = total;

public int ProgressPercentage
{
Expand All @@ -14,10 +14,4 @@ public int ProgressPercentage
return (int)(Received / (double)Total * 100.0);
}
}

public DownloadEvent(long received, long? total)
{
Received = received;
Total = total;
}
}
12 changes: 3 additions & 9 deletions Events/UploadEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

namespace Yove.Http.Events;

public class UploadEvent : EventArgs
public class UploadEvent(long sent, long total) : EventArgs
{
public long Sent { get; }
public long Total { get; }
public long Sent { get; } = sent;
public long Total { get; } = total;

public int ProgressPercentage
{
Expand All @@ -14,10 +14,4 @@ public int ProgressPercentage
return (int)(Sent / (double)Total * 100.0);
}
}

public UploadEvent(long sent, long total)
{
Sent = sent;
Total = total;
}
}
2 changes: 0 additions & 2 deletions Exceptions/ProxyException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,4 @@ public HttpProxyException() { }
public HttpProxyException(string message) : base(message) { }

public HttpProxyException(string message, Exception inner) : base(message, inner) { }

protected HttpProxyException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
Loading

0 comments on commit 9213081

Please sign in to comment.