Skip to content

Commit

Permalink
Added support to upload files via a stream
Browse files Browse the repository at this point in the history
Updated the RequestQuery custom filter
  • Loading branch information
klaasvandeweerdt committed Jul 7, 2023
1 parent 875e256 commit f37e7b8
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 21 deletions.
3 changes: 1 addition & 2 deletions Scr/Sdk4me.GraphQL/Helpers/ExecutionQueryBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -451,8 +451,7 @@ private static string SerializeObject(string? value)
private static string[] SerializeObject(params string?[] values)
{
List<string> retval = new();
if (values == null)
values = Array.Empty<string>();
values ??= Array.Empty<string>();
foreach (string? value in values)
retval.Add(SerializeObject(value));
return retval.ToArray();
Expand Down
2 changes: 1 addition & 1 deletion Scr/Sdk4me.GraphQL/Queries/RequestQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ public RequestQuery SelectWorkflow(WorkflowQuery query)
/// <exception cref="NullReferenceException"></exception>
public RequestQuery CustomFilter(string name, FilterOperator filterOperator, params string?[] values)
{
return AddCustomFilter(name, filterOperator, values ?? new string?[] { null });
return AddCustomFilter(name, filterOperator, values);
}
}
}
70 changes: 52 additions & 18 deletions Scr/Sdk4me.GraphQL/Sdk4meClient.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using Newtonsoft.Json.Converters;
using System.Diagnostics;
using System.Net.Http.Headers;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;

Expand Down Expand Up @@ -312,29 +311,61 @@ public async Task<AttachmentUploadResponse> UploadAttachment(FileInfo file, stri
if (!file.Exists)
throw new FileNotFoundException(file.FullName);

using (FileStream stream = file.OpenRead())
return await UploadAttachment(stream as Stream, file.Name, contentType);
}

/// <summary>
/// Upload a file to the 4me AWS S3 storage.
/// </summary>
/// <param name="stream">The content to upload. The stream needs to support seeking in order to determine the HTTP Content-Length header.</param>
/// <param name="fileName">The file name.</param>
/// <param name="contentType">The content type of the file.</param>
/// <returns>A <see cref="AttachmentUploadResponse"/> containing the 4me AWS S3 file storage reference key and file size.</returns>
/// <exception cref="FileNotFoundException"></exception>
/// <exception cref="Sdk4meException"></exception>
public async Task<AttachmentUploadResponse> UploadAttachment(StreamReader stream, string fileName, string contentType)
{
return await UploadAttachment(stream.BaseStream, fileName, contentType);
}

/// <summary>
/// Upload a file to the 4me AWS S3 storage.
/// </summary>
/// <param name="stream">The content to upload. The stream needs to support seeking in order to determine the HTTP Content-Length header.</param>
/// <param name="fileName">The file name.</param>
/// <param name="contentType">The content type of the file.</param>
/// <returns>A <see cref="AttachmentUploadResponse"/> containing the 4me AWS S3 file storage reference key and file size.</returns>
/// <exception cref="Sdk4meException"></exception>
public async Task<AttachmentUploadResponse> UploadAttachment(Stream stream, string fileName, string contentType)
{
if (!stream.CanSeek)
throw new Sdk4meException("The stream needs to support seeking in order to determine the HTTP Content-Length header.");

DataList<AttachmentStorage> attachmentStorages = await Get<AttachmentStorage>(Query.AttachmentStorage);
if (attachmentStorages.FirstOrDefault() is AttachmentStorage attachmentStorage)
{
if (attachmentStorage.AllowedExtensions != null && attachmentStorage.AllowedExtensions.Contains(file.Extension.TrimStart('.')))
string fileExtension = Path.GetExtension(fileName).TrimStart('.');
if (attachmentStorage.AllowedExtensions != null && attachmentStorage.AllowedExtensions.Contains(fileExtension, StringComparer.InvariantCultureIgnoreCase))
{
if (file.Length >= attachmentStorage.SizeLimit)
if (stream.Length >= attachmentStorage.SizeLimit)
throw new Sdk4meException($"File size exceeded, the maximum size is {attachmentStorage.SizeLimit} byte");

Dictionary<string, string> storageFacility = attachmentStorage?.ProviderParameters?.ToObject<Dictionary<string, string>>() ?? throw new Sdk4meException("File upload failed, invalid AttachmentStorage.ProviderParameters value.");
MultipartFormDataContent multipartContent = new()
{
{ new StringContent(contentType), "Content-Type" },
{ new StringContent(storageFacility["acl"]), "acl" },
{ new StringContent(storageFacility["key"]), "key" },
{ new StringContent(storageFacility["policy"]), "policy" },
{ new StringContent(storageFacility["success_action_status"]), "success_action_status" },
{ new StringContent(storageFacility["x-amz-algorithm"]), "x-amz-algorithm" },
{ new StringContent(storageFacility["x-amz-credential"]), "x-amz-credential" },
{ new StringContent(storageFacility["x-amz-date"]), "x-amz-date" },
{ new StringContent(storageFacility["x-amz-server-side-encryption"]), "x-amz-server-side-encryption" },
{ new StringContent(storageFacility["x-amz-signature"]), "x-amz-signature" },
{ new ByteArrayContent(File.ReadAllBytes(file.FullName)), "file", file.Name }
};
{
{ new StringContent(contentType), "Content-Type" },
{ new StringContent(storageFacility["acl"]), "acl" },
{ new StringContent(storageFacility["key"]), "key" },
{ new StringContent(storageFacility["policy"]), "policy" },
{ new StringContent(storageFacility["success_action_status"]), "success_action_status" },
{ new StringContent(storageFacility["x-amz-algorithm"]), "x-amz-algorithm" },
{ new StringContent(storageFacility["x-amz-credential"]), "x-amz-credential" },
{ new StringContent(storageFacility["x-amz-date"]), "x-amz-date" },
{ new StringContent(storageFacility["x-amz-server-side-encryption"]), "x-amz-server-side-encryption" },
{ new StringContent(storageFacility["x-amz-signature"]), "x-amz-signature" },
{ new StreamContent(stream), "file", fileName }
};

using (HttpRequestMessage requestMessage = new(HttpMethod.Post, attachmentStorage.UploadUri) { Content = multipartContent })
{
Expand All @@ -351,7 +382,7 @@ public async Task<AttachmentUploadResponse> UploadAttachment(FileInfo file, stri
return new()
{
Key = match.Value,
Size = file.Length
Size = stream.Length
};
}
else
Expand All @@ -362,7 +393,10 @@ public async Task<AttachmentUploadResponse> UploadAttachment(FileInfo file, stri
}
}
}
throw new Sdk4meException($"The {file.Extension} extension is not allowed on this 4me instance.");
if (fileExtension == string.Empty)
throw new Sdk4meException($"A file name without extension is not allowed on this 4me instance.");
else
throw new Sdk4meException($"The '{fileExtension}' extension is not allowed on this 4me instance.");
}
throw new Sdk4meException("No AttachmentStorage object returned by the GraphQL API.");
}
Expand Down

0 comments on commit f37e7b8

Please sign in to comment.