so I'm in process of migrating of my app from .NET Framework 4.8 to .NET6. Due to some .NET classes being obsolete in newer version I am experiencing some problems.
I have a controller in which one of endpoints is supposed to return a PDF file. But instead of this what it returns right now is just a JSON file containing only a few values.
Endpoint method:
[HttpPost]
public ActionResult DownloadFile([FromForm] string data, [FromForm] string fileType)
{
try
{
if (!string.IsNullOrWhiteSpace(data))
{
return GenerateReportDocument(data, fileType);
}
}
catch (Exception ex)
{
logger.LogError(ex, $"Unexpected error occured in {nameof(DownloadFile)}.");
return StatusCode(500);
}
return NoContent();
}
Then data is taken into GenerateReportDocument method:
private ActionResult GenerateReportDocument(string data, string fileType)
{
var specificationString = specificationGeneratorService.GenerateSpecificationString(JObject.Parse(data));
logger.LogWarning($"Check images in specificationString: '{specificationString}'");
if (string.IsNullOrWhiteSpace(specificationString))
{
specificationString = "<p></p>";
}
var reportGenerator = generateReportDocuments.SingleOrDefault(r => r.FileType.ToLower().Equals(fileType.ToLower()));
if (reportGenerator is not null)
{
return Ok(reportGenerator.GenerateReportDocument(SpecificationFileName, specificationString));
}
return NoContent();
}
Which then is supposed to be taken into third method:
public HttpContent GenerateReportDocument(string fileName, string specificationString)
{
var requestContent = new StringContent(JsonConvert.SerializeObject(new { Html = specificationString }));
requestContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var httpResponse = Flurl.Url.Combine(_abcPdfOptions.PdfConverterUrl, "pdf/convertfromhtmltopdf")
.PostAsync(requestContent).GetAwaiter().GetResult();
HttpContent httpContent = httpResponse.Content;
httpContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = $"{fileName}.{FileExt}",
};
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
return httpContent;
}
This is how those methods looked like in .NET Framework 4.8 (when they were working correctly, presented in same order as their equivalent methods in .NET6 project):
[HttpPost]
public HttpResponseMessage DownloadFile(HttpRequestMessage requestMessage)
{
try
{
var specification = requestMessage.Content.ReadAsFormDataAsync().Result;
string data = specification.Get("Data");
string fileType = specification.Get("FileType");
if (!string.IsNullOrWhiteSpace(data))
{
return GenerateReportDocument(data, fileType);
}
}
catch (Exception ex)
{
logger.LogError(ex, $"Unexpected error occured in {nameof(DownloadFile)}.");
return new HttpResponseMessage(HttpStatusCode.InternalServerError);
}
return new HttpResponseMessage(HttpStatusCode.NoContent);
}
private HttpResponseMessage GenerateReportDocument(string data, string fileType)
{
var specificationString = specificationGeneratorService.GenerateSpecificationString(JObject.Parse(data));
logger.LogWarning($"Check images in specificationString: '{specificationString}'");
if (string.IsNullOrWhiteSpace(specificationString))
{
specificationString = "<p></p>";
}
var reportGenerator = generateReportDocuments.SingleOrDefault(r => r.FileType.ToLower().Equals(fileType.ToLower()));
if (reportGenerator != null)
{
return new HttpResponseMessage(HttpStatusCode.OK)
{
Content = reportGenerator.GenerateReportDocument(SpecificationFileName, specificationString),
};
}
return new HttpResponseMessage(HttpStatusCode.NoContent);
}
public HttpContent GenerateReportDocument(string fileName, string specificationString)
{
var requestContent = new StringContent(JsonConvert.SerializeObject(new { Html = specificationString }));
requestContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var httpResponse = Flurl.Url.Combine(_abcPdfOptions.PdfConverterUrl, "pdf/convertfromhtmltopdf")
.PostAsync(requestContent).GetAwaiter().GetResult();
HttpContent httpContent = httpResponse.Content;
httpContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = $"{fileName}.{FileExt}",
};
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
return httpContent;
}
I have tried editing my code and changing the methods into IActionResult or HttpResponse, also altering the return types and their arguments. What am I doing wrong? Is ActionResult a good choice for what I'm trying to do?
Did you try returning FileStreamResult/File ?
var fileStream = new FileStream(#"file_path", FileMode.Open);
return new FileStreamResult(fileStream, "application/pdf");
Or
var fileStream = new FileStream(#"file_path", FileMode.Open);
return File(fileStream , "application/pdf", "FileDownloadName.ext");
if you are doing an ajax call to the controller, then no file will be downloaded, you will receive some json data.you need to make a non ajax call so that server will download the file
Related
I am wrote the code to POST from my web application but it is sending 400 bad request.
See the my controller class:
[HttpPost]
public async Task<IActionResult> CreateAgent(AgentCreateDto agentCreateDto)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("https://localhost:44331/api/");
var responseTask = client.PostAsJsonAsync("Agent/CreateAgent", agentCreateDto);
responseTask.Wait();
var result = responseTask.Result;
if (result.IsSuccessStatusCode)
{
var newAgentAdd = JsonConvert.DeserializeObject<AgentCreateDto>(await result.Content.ReadAsStringAsync());
var newAgent = newAgentAdd;
TempData["SuccessMessage"] = $"Agent {newAgent.FirstName} was successfully created.";
return RedirectToAction("AgentLists");
//return RedirectToAction("GetAgentById", new { AgentId = newAgent.usersId});
}
}
return View();
}
Here is below the problem image please see for the reference.
Here is api code for that I am send the request:
[HttpPost("CreateAgent")]
public async Task<IActionResult> CreateAgent([FromForm]AgentCreateDto agentCreateDto)
{
if (!ModelState.IsValid)
{
return BadRequest("Invalid model object");
}
if (agentCreateDto.ProfileImage != null)
{
string uniqueFileName = UploadProfileImage(agentCreateDto.ProfileImage);
agentCreateDto.ProfileNewImage = uniqueFileName;
}
var createAgent = await _userService.CreateAgent(agentCreateDto);
//_logger.LogInformation($"User added to the for file test. ");
return Created("", new
{
Id = createAgent.UsersId,
Message = "Agent created Successfully",
Status = "Success",
UserType = createAgent.UserType
});
}
And for image uploading code at the API side:
private string UploadProfileImage(IFormFile ProfileImage)
{
string uniqueFileName = null;
if (ProfileImage != null)
{
string uploadsFolder = Path.Combine(_webHostEnvironment.ContentRootPath, "ProfileImage");
uniqueFileName = Guid.NewGuid().ToString() + "_" + ProfileImage.FileName;
string filePath = Path.Combine(uploadsFolder, uniqueFileName);
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
ProfileImage.CopyTo(fileStream);
}
}
return uniqueFileName;
}
The correct way to post file and additional data by HttpClient like below:
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("https://localhost:44331/api/");
var formContent = new MultipartFormDataContent();
formContent.Add(new StringContent(agentCreateDto.Id.ToString()), nameof(agentCreateDto.Id));
formContent.Add(new StringContent(agentCreateDto.Message), nameof(agentCreateDto.Message));
formContent.Add(new StringContent(agentCreateDto.UserType), nameof(agentCreateDto.UserType));
//other proerties....
formContent.Add(new StreamContent(agentCreateDto.ProfileImage.OpenReadStream()), nameof(agentCreateDto.ProfileImage), Path.GetFileName(agentCreateDto.ProfileImage.FileName));
//change PostAsJsonAsync to PostAsync.....
var responseTask = client.PostAsync("/Agent/CreateAgent", formContent);
responseTask.Wait();
var result = responseTask.Result;
//more code...
}
I have created a webApi which expect form-data. I am passing both image and data to the WebAPI. When I pass the parameters using PostMan i can recieve data inside model and file is avialable inside HttpContext.Current.Request.Files.
Now i want to pass same data and image to webapi though MVC contoller. Data am able to get in my api method but getting file proving to be a difficult task.
This is my APi method
[Route("Profile/EditUserProfileAsync")]
[HttpPost]
public async Task<HttpResponseMessage> EditUserProfile(UserProfile userProfile)
{
try
{
var Identity = (ClaimsPrincipal)Thread.CurrentPrincipal;
int UserId = Convert.ToInt32(Identity.Claims.Where(c => c.Type == ClaimTypes.Sid).Select(c => c.Value).SingleOrDefault());
if (UserId == 0)
{
return Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "User Not Found!");
}
userProfile.UserId = UserId;
HttpRequestMessage request = this.Request;
if (!request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
var Result = await _userprofile.EditUserProfile(userProfile);
return Request.CreateResponse(HttpStatusCode.Created, Result);
}
catch (Exception ex)
{
await _log.logError(new ErrorLog() { CreatedDate = DateTime.Now, CustomMessage = "Error in EditUserProfile API", ErrorMessage = ex.Message, ModuleName = "UserProfile", StackTrace = ex.StackTrace });
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex.Message);
}
}
This is the method that is being called by the api to save data
public async Task<MethodResult> EditUserProfile(UserProfile userProfile)
{
MethodResult methodResult = new MethodResult();
bool profileComplete = true;
try
{
if (userProfile.ImagePath == null && HttpContext.Current.Request.Files.Count == 0)
{
return new MethodResult() { Success = false, Message = "Profile Image is required !!" };
}
// some code here
}
catch(Exception ex)
{
// log error
}
}
here files count is always comming as zero in the EditUserProfile method in webapi
This the MVC controller code
[Authorize]
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<JsonResult> SaveUserProfileDetails(UserProfile userProfile)
{
string Result = "true";
try
{
var identity = (ClaimsPrincipal)Thread.CurrentPrincipal;
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Remove("Authorization");
client.DefaultRequestHeaders.Add("Authorization", identity.FindFirst("AcessToken").Value);
MultipartFormDataContent form = new MultipartFormDataContent();
form.Add(new StringContent(userProfile.FirstName), "FirstName");
form.Add(new StringContent(userProfile.UserId.ToString()), "UserId");
form.Add(new StringContent(userProfile.LastName), "LastName");
form.Add(new StringContent(userProfile.Designation), "Designation");
form.Add(new StringContent(userProfile.Gender.ToString()), "Gender");
form.Add(new StringContent(userProfile.City), "City");
form.Add(new StringContent(userProfile.Country), "Country");
form.Add(new StringContent(userProfile.DateOfBirth), "DateOfBirth");
form.Add(new StringContent(userProfile.Specialties), "Specialties");
if (Request.Files.Count > 0)
{
MemoryStream ms = new MemoryStream();
Request.InputStream.CopyTo(ms);
byte[] data = ms.ToArray();
ByteArrayContent fileContent = new ByteArrayContent(data);
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { Name = "file"};
form.Add(fileContent);
}
else
{
form.Add(new StringContent(userProfile.ImagePath), "ImagePath");
}
var resp = await client.PostAsync(Constant.ApiBaseUri + "Profile/EditUserProfileAsync", form);
if (resp.IsSuccessStatusCode)
{
var result = await resp.Content.ReadAsStringAsync();
MethodResultVM<string> methodResult = JsonConvert.DeserializeObject<MethodResultVM<string>>(result);
Result = methodResult.Message;
}
else
{
Result = "false";
}
}
catch (Exception ex)
{
Result = "false";
}
return Json(Result, JsonRequestBehavior.AllowGet);
}
with this i am relieving Input stream in header. But i don't want that as android and ios applications are already using the same api and i don't want to modify the api.
Please guide me what can be done to recieve IMAGE in httpcontext in web api controller from httpclient object in mvc controller.
I'm getting a web response via an API which converts file (in this case, Powerpoint presentations to PDF).
I do get the response in a string, but when saving this string to a file or a stream (which ends up being saved in a file anyways) I always end up with a blank file, its size is always well over 0 bytes though.
Here's the class that calls the API:
public class CloudConvert
{
private string apiKey;
private static object ProcessResponse;
public CloudConvert(string apiKey)
{
this.apiKey = apiKey;
}
public async Task<string> Convert(string inputFormat, string outputFormat, string fileUrl)
{
var processUrl = await CreateProcess(inputFormat, outputFormat);
return await Upload(processUrl, fileUrl, outputFormat);
}
private async Task<string> CreateProcess(string inputFormat, string outputFormat)
{
var request = new
{
apikey = apiKey,
inputformat = inputFormat,
outputformat = outputFormat
};
var json = await PostJson("https://api.cloudconvert.com/process", request);
dynamic obj = JObject.Parse(json);
ProcessResponse = obj;
return "https:" + obj.url;
}
private static async Task<string> Upload(string processUrl,
string fileUrl, string outputFormat)
{
var request = new
{
input = "download",
file = fileUrl,
outputformat = outputFormat,
download = "false",
wait = "true",
save = "false"
};
return await PostJson(processUrl, request);
}
private static async Task<string> PostJson(string url, object data)
{
var parameters = JsonConvert.SerializeObject(data);
using (var wc = new WebClient())
{
wc.Headers[HttpRequestHeader.ContentType] = "application/json";
try
{
return await wc.UploadStringTaskAsync(url, "POST", parameters);
}
catch (WebException ex)
{
return string.Empty;
}
}
}
}
And how I'm invoking it:
Task<string> task = Task.Run(async () =>
{
return await cloudConvert.Convert("ppt", "pdf", "http://host.com/myfile.ppt");
});
//I have the PDF in the response, as a string.
var pdfContent = task.Result;
//I think it's here that I'm not handling the resulting string
//properly, ending in a blank file. I've tried writing it to a local file as well, same issue.
using (MemoryStream stream = new MemoryStream())
{
StreamWriter writer = new StreamWriter(stream);
writer.Write(pdfContent);
writer.Flush();
stream.Seek(0, SeekOrigin.Begin);
//This below is something that saves to an Azure storage container...
//filePath = fileStorage.SaveFile($"{fileGeneratedName}.pdf", stream);
//But this fails as well. Blank file
using (FileStream fs = new FileStream(#"c:\tmp\output.pdf", FileMode.OpenOrCreate))
{
stream.CopyTo(fs);
fs.Flush();
}
}
So regardless of how I'm trying to save the returned content, it seems my encoding is wrong. I noticed that the resulting blank file always has the same number of pages than the input Powerpoint presentation.
Any ideas?
Have your convert function return an HttpResponseMessage:
public async Task<HttpResponseMessage> convert()
do your conversion into, say, a memory stream, and then:
var result = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ByteArrayContent(outStream.GetBuffer(),0,(int)outStream.Length)
};
result.Content.Headers.ContentDisposition =
new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
{
FileName = fname
};
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
return result;
I am trying to call the Web api method for saving the File Data.When I debug Webapi method I found that ContentLength is not coming as correct, because of this when i am retrieving the file it is showing error as corrupted file.
My Class method is :-
using (var formData = new MultipartFormDataContent())
{
HttpContent stringContent = new StringContent(file);
formData.Add(stringContent, "file", file);
formData.Add(new StringContent(JsonConvert.SerializeObject(file.Length)), "ContentLength ");
HttpResponseMessage responseFile = client.PostAsync("Report/SaveFile?docId=" + docId, formData).Result;
}
My Web api method is :-
[HttpPost]
public HttpResponseMessage SaveFile(long docId)
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Unauthorized);
try
{
var httpRequest = HttpContext.Current.Request;
bool IsSuccess = true;
if (httpRequest.Files.Count > 0)
{
var docfiles = new List<string>();
foreach (string file in httpRequest.Files)
{
HttpPostedFile postedFile = httpRequest.Files[file];
// Initialize the stream.
Stream myStream = postedFile.InputStream;
myStream.Position = 0;
myStream.Seek(0, SeekOrigin.Begin);
var _item = CorrectedReportLibrary.Services.ReportService.SaveFile(myStream,docId);
response = Request.CreateResponse<bool>((IsSuccess)
? HttpStatusCode.OK
: HttpStatusCode.NoContent,
IsSuccess);
}
}
}
catch (Exception ex)
{
Theranos.Common.Library.Util.LogManager.AddLog(ex, "Error in CorrectedReportAPI.Controllers.SaveDocument()", null);
return Request.CreateResponse<ReportDocumentResult>(HttpStatusCode.InternalServerError, null);
}
return response;
}
How can I set the ContentLength from C# class method?
It looks a bit strange that you use ContentLength as the second parameter on the StringContent class. It is suppose to be which encoding you want to use, for example
new StringContent(content, Encoding.UTF8). I don't think it is the content length that is the issue here.
StringContent class
I guess since it is a file you want to upload, you already have the file read as a stream, so I usually do something like this:
Client:
private async Task UploadFile(MemoryStream file)
{
var client = new HttpClient();
var content = new MultipartFormDataContent();
content.Add(new StreamContent(file));
var result = await client.PostAsync("Report/SaveFile?docId=" + docId, content);
}
Edit. Since it's a multipartform it's easier to let the framework handle the details. Try something like this:
Server:
[HttpPost]
public async Task<HttpResponseMessage> SaveFile(long docId)
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Unauthorized);
try
{
var filedata = await Request.Content.ReadAsMultipartAsync(new MultipartMemoryStreamProvider());
foreach(var file in filedata.Contents)
{
var fileStream = await file.ReadAsStreamAsync();
}
response = Request.CreateResponse<bool>(HttpStatusCode.OK, true);
}
catch (Exception ex)
{
response = Request.CreateResponse<bool>(HttpStatusCode.InternalServerError, false);
}
return response;
}
At Last I found the solution no need to change the web api service,
issue was from client where I was directly passing the file data, Now the modified
working code is like this:-
using (var formData = new MultipartFormDataContent())
{
var bytes = File.ReadAllBytes(file);
formData.Add(new StreamContent(new MemoryStream(bytes)), "file", file);
HttpResponseMessage responseFile = client.PostAsync("ReportInfo/SaveFile?docId=" + docId, formData).Result;
}
In a regular MVC controller, we can output pdf with a FileContentResult.
public FileContentResult Test(TestViewModel vm)
{
var stream = new MemoryStream();
//... add content to the stream.
return File(stream.GetBuffer(), "application/pdf", "test.pdf");
}
But how can we change it into an ApiController?
[HttpPost]
public IHttpActionResult Test(TestViewModel vm)
{
//...
return Ok(pdfOutput);
}
Here is what I've tried but it doesn't seem to work.
[HttpGet]
public IHttpActionResult Test()
{
var stream = new MemoryStream();
//...
var content = new StreamContent(stream);
content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
content.Headers.ContentLength = stream.GetBuffer().Length;
return Ok(content);
}
The returned result displayed in the browser is:
{"Headers":[{"Key":"Content-Type","Value":["application/pdf"]},{"Key":"Content-Length","Value":["152844"]}]}
And there is a similar post on SO: Returning binary file from controller in ASP.NET Web API
. It talks about output an existing file. But I could not make it work with a stream.
Any suggestions?
Instead of returning StreamContent as the Content, I can make it work with ByteArrayContent.
[HttpGet]
public HttpResponseMessage Generate()
{
var stream = new MemoryStream();
// processing the stream.
var result = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ByteArrayContent(stream.ToArray())
};
result.Content.Headers.ContentDisposition =
new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
{
FileName = "CertificationCard.pdf"
};
result.Content.Headers.ContentType =
new MediaTypeHeaderValue("application/octet-stream");
return result;
}
If you want to return IHttpActionResult you can do it like this:
[HttpGet]
public IHttpActionResult Test()
{
var stream = new MemoryStream();
var result = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ByteArrayContent(stream.GetBuffer())
};
result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
{
FileName = "test.pdf"
};
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
var response = ResponseMessage(result);
return response;
}
This question helped me.
So, try this:
Controller code:
[HttpGet]
public HttpResponseMessage Test()
{
var path = System.Web.HttpContext.Current.Server.MapPath("~/Content/test.docx");;
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
var stream = new FileStream(path, FileMode.Open);
result.Content = new StreamContent(stream);
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = Path.GetFileName(path);
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
result.Content.Headers.ContentLength = stream.Length;
return result;
}
View Html markup (with click event and simple url):
<script type="text/javascript">
$(document).ready(function () {
$("#btn").click(function () {
// httproute = "" - using this to construct proper web api links.
window.location.href = "#Url.Action("GetFile", "Data", new { httproute = "" })";
});
});
</script>
<button id="btn">
Button text
</button>
Data
Here is an implementation that streams the file's content out without buffering it (buffering in byte[] / MemoryStream, etc. can be a server problem if it's a big file).
public class FileResult : IHttpActionResult
{
public FileResult(string filePath)
{
if (filePath == null)
throw new ArgumentNullException(nameof(filePath));
FilePath = filePath;
}
public string FilePath { get; }
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StreamContent(File.OpenRead(FilePath));
var contentType = MimeMapping.GetMimeMapping(Path.GetExtension(FilePath));
response.Content.Headers.ContentType = new MediaTypeHeaderValue(contentType);
return Task.FromResult(response);
}
}
It can be simply used like this:
public class MyController : ApiController
{
public IHttpActionResult Get()
{
string filePath = GetSomeValidFilePath();
return new FileResult(filePath);
}
}
I am not exactly sure which part to blame, but here's why MemoryStream doesn't work for you:
As you write to MemoryStream, it increments its Position property.
The constructor of StreamContent takes into account the stream's current Position. So if you write to the stream, then pass it to StreamContent, the response will start from the nothingness at the end of the stream.
There's two ways to properly fix this:
construct content, write to stream
[HttpGet]
public HttpResponseMessage Test()
{
var stream = new MemoryStream();
var response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StreamContent(stream);
// ...
// stream.Write(...);
// ...
return response;
}
write to stream, reset position, construct content
[HttpGet]
public HttpResponseMessage Test()
{
var stream = new MemoryStream();
// ...
// stream.Write(...);
// ...
stream.Position = 0;
var response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StreamContent(stream);
return response;
}
looks a little better if you have a fresh Stream, 1) is simpler if your stream does not start at 0
For me it was the difference between
var response = Request.CreateResponse(HttpStatusCode.OK, new StringContent(log, System.Text.Encoding.UTF8, "application/octet-stream");
and
var response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(log, System.Text.Encoding.UTF8, "application/octet-stream");
The first one was returning the JSON representation of StringContent: {"Headers":[{"Key":"Content-Type","Value":["application/octet-stream; charset=utf-8"]}]}
While the second one was returning the file proper.
It seems that Request.CreateResponse has an overload that takes a string as the second parameter and this seems to have been what was causing the StringContent object itself to be rendered as a string, instead of the actual content.
I found this article useful: https://codeburst.io/download-files-using-web-api-ae1d1025f0a9
Basically it says:
[Route("api/[controller]")]
[ApiController]
public class JobController : ControllerBase
{
[HttpGet]
public ActionResult GetFile()
{
byte[] fileContent = GetFile();
return File(fileContent, "application/pdf", "test.pdf");
}
}
var memoryStream = new MemoryStream();
await cloudFile.DownloadToStreamAsync(memoryStream);
responseMessage.result = "Success";
var contentType = "application/octet-stream";
**using (var stream = new MemoryStream())
{
return File(memoryStream.GetBuffer(), contentType, "Cartage.pdf");
}**