Posting file from mvc controller to webAPI service - c#

a little background on our system, we have a mvc application that creates and displays forms, then posts these forms to a controller within the mvc application. it then does verification etc. etc.
I want to be able to use this to upload a file (currently using a post with the contoller pulling out the httppostedfilebase) have it send that file to a seperate application API which will pull the file information, store the information in the database, and save the file as something generic.
I have a method that can do all the pull apart/save file stuff, I have a controller that accepts my form post and gets all the relevant data including an httppostedfilebase. What I need is a way to send that file (which is not saved yet) over to our API.
We are hoping to avoid turning the file into a base64 string.
This is in c#.

Have you looked at this answer:
Web API: how to access multipart form values when using MultipartMemoryStreamProvider?
I think it will provide some ideas on how to handle streaming files in memory.

Solution we used:
using HttpPostedFileBase from the multipart form,
create byte array
stream file contents into the byte array
convert byte array to base64 string
add to json object along with file headers (name and extension)
post json object to api using HttpClient

Related

Which data type in Asp Net Core C# can be used to catch Angular's blob object?

I have a BLOB object of an image in Angular 5, which I want to send it to backend via api. In backend which data type shall I use to capture the same. I am aware that in previous versions of Asp.Net there was 'HttpBaseType' but in core it is not available.
Therefore which datatype to be used for getting BLOB object of Angular in Asp.Net core c#?
Update: My use case is that I am drawing an image using canvas and getting its BLOB in Angular. Now I want this blob to be received at back-end. But I am not getting suitable type for the same. Here there is no involvement of file at all!
(I am not trying to upload the image/file)
Angular's blobs are merely just files (most of the time). You should be able to use ASP.NET Core's IFormFile to easily capture incoming data.
Blobs are merely files, if you are sending that request already, inspect your
browser and look at the raw request. If you do not want to use files then you'll have to create your own way of parsing the data.
I read some posts on it and it seems that Angular sends blobs attached as a file to a form. If you still don't want to do that then you can follow this post to encode it as base64 and do it yourself.
Here's how I would do it using IFormFile:
[HttpPost("upload_blob")]
public async Task<IActionResult> Post(IFormFile file)
{
Console.WriteLine(file.ContentType);
// process uploaded files
// Don't rely on or trust the FileName property without validation.
return Ok("some result");
}
Lastly, here are some posts you can look at:
MDN post about blobs
IFormFile example by Microsoft
IFormFile documentation
I hope I was of help, cheers!

Web api deserialization

I receive in a request from a web api project a parameter that represents the URL to a json or xml file.
What i have to do is to download this file, deserialize it and the process it.
In the past i was writting two individual methods :
one method that was reading the file using linq to xml
another method that reading the file using newtonsoft.json
I am wondering is there a way so that web api can deserialize automatically this url link / file for me ?

How do I create a link to a file I have saved as a memory stream in a SQL table?

My web application (C# and ASP.Net) allows someone to upload a jpg/pdf file and save it as a memory stream inside a SQL table. This is what it looks like once written in the table:
0xFFD8FFE000104A4649.....
Now I want to provide this file back on my web interface through a link where the user can download this file. I have retrieved my file by converting the string above back to a byte array using
filedata = Encoding.ASCII.GetBytes(<string above>);
Then I called this:
string filename = "pic.jpg";
File.WriteAllBytes(filename, filedata);
But I have no clue how I should post this back to the user as a downloadable link on my web interface. Do I have to save this file to a temporary folder on my server or is there a way that I could invoke a call to render my file back as a picture where the user will be prompted to save the file or open it?
Thank you!
You will need to create a page / action / function that writes the bits back as the response to an HTTP request. Keep in mind that in doing so you will probably need to set the proper Content-Type header in the response according to what your file is.
So, you generate a link that calls your page / action / function. Then That sends the binary data back in an HTTP response. Something like
pic.jpg
If you some detail as to what framework you're using (MVC, WebForms, etc) then we can give more detailed examples.
Depending on how you want to present the image.
If you want to embed the image in the web return an link to the file with
string filename = Path.Combine(HttpRuntime.AppDomainAppPath, "Content/Images/pic.jpg");
File.WriteAllBytes(filename, filedata);
return filename;
then in the JavaScript side create an img element with thatsrc
Or if you want the user to download the file do what #squillman says in his answer

How to send a PDF from Web API to MVC app for direct download

I have a ASP.NET MVC app with a controller action which is triggered by a button press on my view. The controller action in turn calls a ASP.NET Web API. The Web API calls a third, outside system and asks for a PDF to be created at a network location. The Web API then picks up the PDF from the network location, converts it into a byte array, and returns the byte array from the Web API.
I have verified the PDF is generated properly by the third party application. I went to the network location and could open the PDF successfully.
At this point, I am back in my original MVC controller action, with a byte array. I now need to return the byte array to the browser as a PDF file for direct download, versus opening the PDF file. I have found answers such as this suggesting using the WriteAllBytes method to write the file. In my case though, I don't want to write the file to disk but instead want to return the file as a download to the user.
Also, I am not sure if I need to decode the byte array in my MVC app before attempting to send to the user for download. Does the Web API encode it as Base64 when it returns it?
This is a simplified version of my Web API code:
public byte[] GetPdf (int accountNumber)
{
string filePath = _outsideServiceManager.RequestPdfCreation(accountNumber);
byte[] pdfBytes = System.IO.File.ReadAllBytes(filePath);
return pdfBytes;
}
And this is a simplified version of my MVC controller action code. I am using the overload of the Controller.File method which accepts a byte array.
public ActionResult DownloadPdf (int accountNumber)
{
byte[] pdfFileAsByteArray = _serviceManager.GetPdf(accountNumber);
return File(pdfFileAsByteArray, "application/pdf", "AccountSummary.pdf");
}
Right now I do successfully pick up the PDF file, convert it to a byte array, and successfully receive it in the MVC app. It does directly download to the user's browser, but when you try to open it with a PDF reader it says that the PDF file is corrupted.
How should I construct this flow?
EDIT: One observation I made was that the byte array might be 26 kb in the Web API, but closer to 34 kb when it is retrieved in the MVC app. Does this indicate encoding that has to be undone before accessing the file?
As Chris mentioned in a comment, the issue was with the response from the WebAPI. The byte array was automatically being encoded as a Base64 string, so when I tried to use that byte array in the client without decoding it first, it didn't work.
What I had to do was change my MVC app code to use ReadAsStringAsync versus ReadAsByteArrayAsync.
Then I had to remove the first and last character of the string as extra quotation marks were inserted for some reason, which would cause my subsequent conversion attempt to fail.
After that, I just used Convert.FromBase64String to decode the string and convert it into a byte array. The PDF files are now viewable.
You need to add the extension to the filename parameter:
return File(pdfFileAsByteArray, "application/pdf", "AccountSummary");
should be
return File(pdfFileAsByteArray, "application/pdf", "AccountSummary.pdf");
I think what you'll need to do is have the WebApi response be a simple HttpResponseMessage, with a StreamContent inside. Then you can simply have MVC return the stream.

Forward file upload details to another remote service

I have a service for uploading files which works well.
Is it possible to submit a file upload to a asp.net method (like normal uploads), but then forward the upload file details to the remote service. Therefore using the asp.net method as a proxy and NOT actual upload method?
The actual file saving will be done at the remote service.
Note
I'm using c# and .net 3.5
Regards
If you are using an ASP.NET method, the file MUST be uploaded to the server. However, it doesn't have to be saved using the "SaveAs" method or any other method. You can access the file directly as a stream which you can pass to your other service if you can send streams to it.
The idea is explained in this blog post (slightly different use but same idea):
http://weblogs.asp.net/meligy/archive/2008/02/18/unit-test-friendly-file-upload-handling-in-n-tier-applications.aspx
So, if your remote service call can be simplified as a method like:
public void MyServiceMethod(Stream inputStream) { ........ }
You can pass the file content from the page without saving it some way like:
myService.MyServiceMethod(myFileUploadControl.PostedFile.InputStream);

Categories