Sending byte[] representing zip file from one API to another - c#

I am trying to send a zip file I create in one API (lets call this 'API 1') to another (aka 'API 2').
Originally I attempted to just send the byte[] as the response in API 1 but when accessing the response within API 2, the byte[] was a different size and the file was corrupt. I then attempted to convert the byte[] in API 1 to a base64 string and then decode in API 2, but realised the strings were not the same and again, the file was corrupt.
Here is my code as it currently stands...
API 1 Code
[HttpPost]
public IActionResult BuildZipFile(Custom myObject)
{
CODE HERE WHICH GENERATES ZIP FILE
byte[] zipFile = System.IO.File.ReadAllBytes(ZIP FILE PATH);
return Ok(Convert.ToBase64String(zipFile));
}
API 2 Code
[HttpPost]
public IActionResult RetrieveZipFile(Custom myObject)
{
RestClient client = new RestClient(#"https://localhost:44323/api/ProcessBuild");
RestRequest request = new RestRequest(Method.POST);
request.AddHeader("content-type", "application/json");
request.AddParameter("application/json", JsonConvert.SerializeObject(myObject), ParameterType.RequestBody);
var response = client.Execute(request);
byte[] retrievedZipFile = Convert.FromBase64String(response.Content);
return File(retrievedZipFile, "application/zip", process.Name + ".zip");
}
Currently this returns a zip file which is corrupt. Any help on this would be greatly appreciated!

I am not sure about the mime type. This should work fine. I am not familiar with RestSharp.
using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return File(System.IO.File.OpenRead(filePath), "application/zip");
}

Related

String to byte array to file for POST request

I am retrieving a PDF file from SharePoint that comes in as text (not plain, encoded). I want to turn this into an actual PDF file to then upload it to another URL via a POST request.
var client2 = new RestClient("https://preactdk.redacted.com/sites/mysite/_api/web/GetFileByServerRelativeUrl('/sites/mysite/Shared%20Documents/testfolder/test.pdf')/$value");
client2.Timeout = -1;
var request2 = new RestRequest(Method.GET);
request2.AddHeader("Authorization", $"Bearer {tokenData.access_token}");
request2.AddHeader("Accept", "application/json;odata=verbose");
IRestResponse response2 = client2.Execute(request2);
string content = response2.Content;
byte[] bytes = Encoding.ASCII.GetBytes(content);
var myfile = System.IO.File.WriteAllBytes("test.pdf", bytes);
var clientUpload = new RestClient("https://mysite.azurewebsites.net/api/Upload");
RestRequest requestUpload = new RestRequest(Method.POST);
//requestUpload.AddHeader("Content-Type", "multipart/form-data");
requestUpload.AddFile("File", bytes, "test.pdf");
var responseUpload = clientUpload.Post(requestUpload);
I've tried to convert it to a byte array but without much success. How do I create the PDF in memory stream or file stream and pass it to the POST request function ? This function takes a pdf file in its body via POST.
What I needed was to use
byte[] bytes = response2.RawBytes;
directly. It worked smoothly and the PDF displays correctly.

Send a 'Stream' over a PutAsync request

I'm trying my hand at .NET Core but I'm stuck trying to convert multipart/form-data to an application/octet-stream to send via a PUT request. Anybody have any expertise I could borrow?
[HttpPost("fooBar"), ActionName("FooBar")]
public async Task<IActionResult> PostFooBar() {
HttpResponseMessage putResponse = await _httpClient.PutAsync(url, HttpContext.Request.Body);
}
Update: I think I might have two issues here:
My input format is multipart/form-data so I need to split out the file from the form data.
My output format must be application-octet stream but PutAsync expects HttpContent.
I had been trying to do something similar and having issues. I needed to PUT large files (>1.5GB) to a bucket on Amazon S3 using a pre-signed URL. The implementation on Amazon for .NET would fail for large files.
Here was my solution:
static HttpClient client = new HttpClient();
client.Timeout = TimeSpan.FromMinutes(60);
static async Task<bool> UploadLargeObjectAsync(string presignedUrl, string file)
{
Console.WriteLine("Uploading " + file + " to bucket...");
try
{
StreamContent strm = new StreamContent(new FileStream(file, FileMode.Open, FileAccess.Read));
strm.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
HttpResponseMessage putRespMsg = await client.PutAsync(presignedUrl, strm);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return false;
}
return true;
}
Turns out Request has a Form property that contains a Files property that has an OpenReadStream() function on it to convert it into a stream. How exactly I was supposed to know that, I'm not sure.
Either way, here's the solution:
StreamContent stream = new StreamContent(HttpContext.Request.Form.Files[0].OpenReadStream());
HttpResponseMessage putResponse = await _httpClient.PutAsync(url, stream);

How to Post a web request and receive a file from web API response?

I have an Infopath Form Template on Sharepoint, I want to add a button there so when the user clicks on it, it will POST an string to the following Web API. The following web API is tested and returns an excel file as shown:
I want to Post the FileName of the excel file using post request and it is important for me the request method to be POST type. and then the user will download a file with the specified 'FileName'.
Actually i want to use post method because at the next stage i will send the content of the excel file too.
Important Note: I only can use .Net FrameWork 3.5 because this is the only framework supported in InfoPath Form Templates.
[HttpPost]
public HttpResponseMessage Post([FromBody]string FileName)
{
string reqBook = "c:\somefile.xlsx";
//converting Excel(xlsx) file into bytes array
var dataBytes = File.ReadAllBytes(reqBook);
//adding bytes to memory stream
var dataStream = new MemoryStream(dataBytes);
HttpResponseMessage httpResponseMessage = Request.CreateResponse(HttpStatusCode.OK);
httpResponseMessage.Content = new StreamContent(dataStream);
httpResponseMessage.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
httpResponseMessage.Content.Headers.ContentDisposition.FileName = FileName;
httpResponseMessage.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
return httpResponseMessage;
}
When you perform the HttpPost on the client side, you will want to read the HttpResponseStream to get the byte data of the response stream.
Once you have the response stream data, you can then deserialize it to the type of object in C# you want, or you could alternatively just write it to the disk as
File.WriteAllBytes("someexcel.xlsx",data);
An easy way to do it would be with the HttpClient class.
HttpClient client = new HttpClient();
var response = client.PostAsync("", null).Result;
var content = response.Content.ReadAsByteArrayAsync().Result;
File.WriteAllBytes("excel.xlsx", content);
Just fill in the PostAsync bit with the Url and the content you wish to post.
I am using .Result to keep everything synchronous - but you can use 'await' if you prefer.
If you are working with HttpWebRequests - then the process becomes more complicated, as you need to manage the streams yourself.
The HttpClient will manage and handle it all for you - so I recommend it, unless there is something special it needs to do that it currently does not.
Due to your .Net 3.5 requirement:
private static HttpWebResponse MakeRequest(string url, string postArgument)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "multipart/form-data;";
Stream stream = request.GetRequestStream();
string result = string.Format("arg1={0}", postArgument);
byte[] value = Encoding.UTF8.GetBytes(result);
stream.Write(value, 0, value.Length);
stream.Close();
return (HttpWebResponse)request.GetResponse();
}
You can then do:
var response = MakeRequest("http://mywebsite.com/ProcessExcel", "accounts.xlsx");
And then do
Stream objStream = response .GetResponseStream();
BinaryReader breader = new BinaryReader(objStream);
byte[] data= breader.ReadBytes((int)webresponse.ContentLength);
File.WriteAllBytes("excel.xlsx",data);

Encoding issue with file on AWS Lambda/API Gateway

I'm producing a REST API that does some file conversion / processing.
My Visual Studio 2015 and building on an AWS Serverless Core - ASP.Net Core Web API template.
I'm running some initial test methods and have encountered what appears to be an encoding issue.
My controller has the following. It simply pulls the posted file into a byte array via a memory stream and then passes it back. (The final application will process the byte array)
[HttpPost]
public IActionResult Post(IFormFile file)
{
var inputStream = new MemoryStream();
file.CopyTo(inputStream);
var fileBytes = inputStream.ToArray();
var outputStream = new MemoryStream(fileBytes);
return File(outputStream, "application/octet-stream");
}
I then have a test application I'm using to pass a file to this controller and save the return.
using (var client = new HttpClient())
{
using (var content = new MultipartFormDataContent())
{
var inputFileStream = new FileStream(Server.MapPath("~/App_Data/InputFile.pdf"), FileMode.Open, FileAccess.Read);
var inputFileBytes = new Byte[inputFileStream.Length];
inputFileStream.Read(inputFileBytes, 0, inputFileBytes.Length);
inputFileStream.Close();
content.Add(new ByteArrayContent(inputFileBytes), "file", "InputFile.pdf");
var requestUri = "http://localhost:5000/api/controller";
//var requestUri = "https://xxxxxxxxxx.execute-api.eu-west-1.amazonaws.com/Prod/api/controller";
var result = client.PostAsync(requestUri, content).Result;
var resultStream = result.Content.ReadAsStreamAsync().Result;
var memoryStream = new MemoryStream();
resultStream.CopyTo(memoryStream);
var outputFileBytes = memoryStream.ToArray();
FileStream outputFileStream = new FileStream(Server.MapPath("~/App_Data/OutputFile.pdf"), FileMode.Create, FileAccess.ReadWrite);
outputFileStream.Write(outputFileBytes, 0, outputFileBytes.Length);
outputFileStream.Close();
}
}
When I run using the localhost application, the duplicate file is saved back. However, when I publish the API to AWS, the file returned is exactly double in size to the original, certainly indicated an encoding issue.
If I pass an ANSI text file with the contents TEST then the saved file contains VEVTVA==
Can someone point me at where I should be setting any encoding settings and any suggested settings to ensure that the output stream from my HttpClient is the same as my input?
So I noticed this as well with a AWS ASP.Net Core Web API. I changed the MIME type from application/octet-stream to application/text and that seemed to fix it on AWS.
[HttpPost]
public IActionResult Post(IFormFile file)
{
var inputStream = new MemoryStream();
file.CopyTo(inputStream);
var fileBytes = inputStream.ToArray();
var outputStream = new MemoryStream(fileBytes);
return File(outputStream, "application/text");
}

Upload file on Dropbox using REST api

Below code uploads files on a server with same name, size and file type (like it's uploading a dummy file). But when do I try to view it, it shows noting. When I try to upload a .txt file it works. What's wrong?
public static void UploadFile(string accessToken,string path,HttpPostedFileBase file)
{
try
{
var client = new RestClient("https://content.dropboxapi.com/1/files_put/auto/Abc/" + file.FileName);
var request = new RestRequest(Method.PUT);
request.AddHeader("Authorization", "Bearer " + accessToken);
request.AddHeader("Content-Type", file.ContentType);
//request.AddHeader("Content-Length", file.ContentLength.ToString());
request.AddFile("file", path);
IRestResponse response = client.Execute(request);
}
catch (Exception ex)
{
throw ex;
}
}
I assume from the classes I see that you're using RestSharp? I'm not all that familiar, but from a quick search, it doesn't look like AddFile does what you want. (That sets up a multipart form upload, which is not what the Dropbox API expects.)
Instead of request.AddFile(...), I think you want something like this (completely untested):
// Get a byte array of the file content. Note that this involves reading
// the entire file into memory! I couldn't immediately find a way to work
// with the stream itself in RestSharp.
MemoryStream target = new MemoryStream();
file.InputStream.CopyTo(target);
byte[] data = target.ToArray();
// Send those bytes as the body of your HTTP request.
request.AddParameter("application/octet-stream", data, ParameterType.RequestBody);

Categories

Resources