I have an ASP.Net Web API set up on my website that is used to communicated with a WPF desktop application. I have an action setup on the API to receive binary files from the client application. However in some (seemingly random) cases when I get all the bytes from the request not all the bytes are read. Hopefully you can give me an idea of how to do this in a way that will work all of the time. Here's the code:
Client Side:
public static SubmitTurnResult SubmitTurn(int turnId, Stream fileStream)
{
HttpClient client = CreateHttpClient();
HttpContent content = new StreamContent(fileStream);
content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
content.Headers.ContentDisposition.FileName = "new-turn.Civ5Save";
content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
content.Headers.ContentLength = fileStream.Length;
HttpResponseMessage response = client.PostAsync(
string.Format("SubmitTurn?authKey={0}&turnId={1}",
LocalSettings.Instance.AuthenticationKey,
turnId
),
content
).Result;
response.EnsureSuccessStatusCode();
return response.Content.ReadAsAsync<SubmitTurnResult>().Result;
}
SubmitTurnResult is an enum that defines the result on the server, turnId is the ID for the entity this file is attached to, and fileStream is an actual FileStream reading the bytes of disk.
Server Side:
[HttpGet, HttpPost]
public SubmitTurnResult SubmitTurn(string authKey, int turnId)
{
try
{
bool worked = false;
int gameId = 0;
using (GmrEntities gmrDb = new GmrEntities())
{
var player = gmrDb.Users.FirstOrDefault(u => u.AuthKey == authKey);
if (player != null)
{
var turn = player.Turns.FirstOrDefault(t => t.TurnID == turnId);
if (turn != null)
{
byte[] saveFileBytes = null;
using (MemoryStream tempStream = new MemoryStream())
{
var task = this.Request.Content.CopyToAsync(tempStream);
task.Wait();
saveFileBytes = tempStream.ToArray();
tempStream.Close();
}
if (saveFileBytes.Length != this.Request.Content.Headers.ContentLength.Value)
{
throw new Exception(string.Format("Byte array length ({0}) not equal to HTTP content-length header ({1}). This is not good!",
saveFileBytes.Length, this.Request.Content.Headers.ContentLength.Value));
}
worked = GameManager.SubmitTurn(turn, saveFileBytes, gmrDb);
if (worked)
{
gameId = turn.Game.GameID;
gmrDb.SaveChanges();
}
}
}
}
return SubmitTurnResult.OK;
}
catch (Exception exc)
{
DebugLogger.WriteExceptionWithComments(exc, string.Format("Diplomacy: Sumbitting turn for turnId: {0}", turnId));
return SubmitTurnResult.UnexpectedError;
}
}
As noted in my previous comment, we ran into this same behavior with StreamContent, but when streaming a response from a Windows Server 2003 Web API service. It doesn't repro on 2008. Actually, it also repros on Windows Server 2008 if I configure the VM with a small amount of RAM (712 MB), but with 4 GB of RAM it doesn't repro. Also, we found that this only repros with a FileStream. Converting the FileStream to a MemoryStream bypasses the issue (at the expense of memory of course). We found that when the response stream terminates early, it's always on a 4096-byte boundary, and it hits a cap at around 3.5MB.
Here's the workaround that fixed things for me, tailored to your code example:
public static SubmitTurnResult SubmitTurn(int turnId, Stream fileStream)
{
HttpClient client = CreateHttpClient();
var memoryStream = new MemoryStream((int)fileStream.Length);
fileStream.CopyTo(memoryStream);
fileStream.Close();
memoryStream.Seek(0, SeekOrigin.Begin);
HttpContent content = new StreamContent(memoryStream);
If desired, you can conditionally do the MemoryStream copy only when Stream is a FileStream.
Related
I am building an C# Console Application for GET file which will automatically download the file when I run the console application.
These are my codes:
using System;
using System.Diagnostics;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
namespace WebAPIConsoleNEW
{
class Program
{
static void Main(string[] args)
{
RunAsync().Wait();
}
static async Task RunAsync()
{
string bookPath_Pdf = #"D:\VisualStudio\randomfile.pdf";
string bookPath_xls = #"D:\VisualStudio\randomfile.xls";
string bookPath_doc = #"D:\VisualStudio\randomfile.docx";
string bookPath_zip = #"D:\VisualStudio\randomfile.zip";
string format = "pdf";
string reqBook = format.ToLower() == "pdf" ? bookPath_Pdf : (format.ToLower() == "xls" ? bookPath_xls : (format.ToLower() == "doc" ? bookPath_doc : bookPath_zip));
string fileName = "sample." + format.ToLower();
try
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:49209/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("applicaiton/json"));
Console.WriteLine("GET");
//converting Pdf file into bytes array
var dataBytes = File.ReadAllBytes(reqBook);
//adding bytes to memory stream
var dataStream = new MemoryStream(dataBytes);
//send request asynchronously
HttpResponseMessage response = await client.GetAsync("api/person");
response.Content = new StreamContent(dataStream);
response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentDisposition.FileName = fileName;
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
//Check that response was successful or throw exception
//response.EnsureSuccessStatusCode();
//Read response asynchronously and save asynchronously to file
if (response.IsSuccessStatusCode)
{
using (var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost:49209/api"))
{
using (
Stream contentStream = await (await client.SendAsync(request)).Content.ReadAsStreamAsync(),
fileStream = new FileStream("D:\\VisualStudio\\randomfile.pdf", FileMode.Create, FileAccess.Write, FileShare.None))
{
//copy the content from response to filestream
await response.Content.CopyToAsync(fileStream);
//Console.WriteLine();
}
}
}
}
catch (HttpRequestException rex)
{
Console.WriteLine(rex.ToString());
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
}
When I run another ASP.NET application which is my localhost, it only return the default which is value1 and value2 in the Controller. However, I do not have Controller in C# Console Application. I think I just one step away, I had successfully obtain the file and CopyToAsync the file I wanted to download.
Conclusion:
I want when user runs the application it would straight download the file in a place (or can I use SaveFileDialog to let user decide where to save the file).
Please help thanks
Update:
At first, I created a ASP.NET Web Application and Create a PersonController and I run the Project. After that I created a console C# Application and then I want to achieve the result of when user runs the console C# Application it would straight download the file to a specific place.
In the first get I uses api/person, and I convert the file int o bytes array and add the bytes array to memory stream. After that, I don't really know what I'm doing is right or wrong. I saw something like CopyToAsync is working then I tried it and implement it but it won't works. My goal is simple I just want to acheive once I run the C# Console application it would straight download the file from a specific localhost address
Well I think your problem is that you are sending two GET requests, in case you just want to call api/student then save the response into a file then no need for the second request
var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost:49209/api")//no need for it
So your code should be like this:
static async Task RunAsync()
{
string bookPath_Pdf = #"D:\VisualStudio\randomfile.pdf";
string bookPath_xls = #"D:\VisualStudio\randomfile.xls";
string bookPath_doc = #"D:\VisualStudio\randomfile.docx";
string bookPath_zip = #"D:\VisualStudio\randomfile.zip";
string format = "pdf";
string reqBook = format.ToLower() == "pdf" ? bookPath_Pdf : (format.ToLower() == "xls" ? bookPath_xls : (format.ToLower() == "doc" ? bookPath_doc : bookPath_zip));
string fileName = "sample." + format.ToLower();
try
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:49209/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("applicaiton/json"));
Console.WriteLine("GET");
//converting Pdf file into bytes array
var dataBytes = File.ReadAllBytes(reqBook);
//adding bytes to memory stream
var dataStream = new MemoryStream(dataBytes);
//send request asynchronously
HttpResponseMessage response = await client.GetAsync("api/person");
response.Content = new StreamContent(dataStream);
response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentDisposition.FileName = fileName;
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
//Check that response was successful or throw exception
//response.EnsureSuccessStatusCode();
//Read response asynchronously and save asynchronously to file
if (response.IsSuccessStatusCode)
{
using (Stream contentStream = await response.Content.ReadAsStreamAsync())
{
using (fileStream = new FileStream("D:\\VisualStudio\\randomfile.pdf", FileMode.Create, FileAccess.Write, FileShare.None))
{
//copy the content from response to filestream
await response.Content.CopyToAsync(fileStream);
//Console.WriteLine();
}
}
}
}
}
catch (HttpRequestException rex)
{
Console.WriteLine(rex.ToString());
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
Also it would be good to print a message for the user telling him that logging data from server into file(File path) is in progress:
static void Main(string[] args)
{
Console.WriteLine("Logging data from server into file (D:\\VisualStudio\\randomfile.pdf");
RunAsync().Wait();
}
I'm using .Net Core 2.0 to develop my ASP.Net API and I want to make request for external public stream and forward it with my own GET route.
The external stream is an MJPEG content-type.
Since I'm using the latest version of .NET Core, the PushStreamContent is not available anymore.
This is the class that takes care of the Connection and Stream process:
internal class LiveViewStream
{
HttpClient _client = new HttpClient();
WebClient webClient = new WebClient();
public Stream outputStream = new MemoryStream();
public Stream GetVideoTCP()
{
string url = "http://87.139.76.248:8081/cgi-bin/faststream.jpg";
return webClient.OpenRead(url);
}
public void Main()
{
var bytesRead = 0;
var buffer = new byte[65536];
using (Stream stream = GetVideoTCP())
{
do
{
bytesRead = stream.Read(buffer, 0, buffer.Length);
outputStream.Write(buffer, 0, bytesRead);
}
while (stream.Position != stream.Length);
}
}
And this is the GET route:
// GET: api/<controller>
[HttpGet]
public HttpResponseMessage Get()
{
var video = new LiveViewStream();
video.Main();
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StreamContent(video.outputStream);
response.Content.Headers.ContentType = new MediaTypeHeaderValue("video/x-motion-jpeg");
return response;
}
This code gives me error with while method not being supported. I have tried different methods, and they didn't work, I would either get a file when making a GET request or nothing.
Can anyone help me with this please?
I resolved this issue by using Socket TCP server and forwarding the images with a custom MjpegWriter to client-socket.
I'd like to create:
an ASP.NET Core 1.1 Web Application in VS2017 with one HttpGet Endpoint
The endpoint should stream random Values between 0 and 255
Every 20ms the value should change.
The Client should never stop reading the stream and as fast as possible get the new values.
So far this is my Code:
Client
public async Task SubscribeToUpdates()
{
this.subscribe = false;
try
{
var client = new HttpClient();
var stream = await client.GetStreamAsync(Constants.SubscribeEndpoint);
using (var rdr = new StreamReader(stream))
{
while (!rdr.EndOfStream && !subscribe)
{
var result = rdr.ReadLine();
var json = JObject.Parse(result);
this.HandleUpdateResult(json); // todo
}
}
}
catch (Exception e)
{
// TO do: log exception
}
}
Server, not working
[HttpGet]
public Task PushStreamContent()
{
HttpContext.Response.ContentType = "text/event-stream";
var sourceStream = randomStream();
return sourceStream.CopyToAsync(HttpContext.Response.Body);
}
public static Stream randomStream()
{
Random rnd = new Random();
MemoryStream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(JsonConvert.SerializeObject(rnd.News(0,255));
writer.Flush();
stream.Position = 0;
return stream;
}
Question:
How to rewrite Server function to create the unlimited stream?
Other solutions are also welcome, as long as they keep in mind that they are .net core conform and enable the client to get as fast as possible the latest information.
Working Full .Net Version
I've managed to write the Code for .net Standard, but not for .net core. Reason for this is that PushStreamContent does not exist in .net core :/.
[HttpGet]
public HttpResponseMessage PushStreamContent()
{
var response = Request.CreateResponse(HttpStatusCode.Accepted);
response.Content =
new PushStreamContent((stream, content, context) =>
{
var plotter = new Plotter();
while (true)
{
using (var writer = new StreamWriter(stream))
{
Random rnd = new Random()
writer.WriteLine(rnd.Next(0,255));
stream.Flush();
Thread.Sleep(20);
}
}
});
return response;
}
Thanks to the previous Answer from "Mike McCaughan" and "Joel Harkes", i've rethinked the communcation process and switched from REST to Websockets.
You can find a good Example how to use WebSockets in .net Core (and Xamarin.Forms) here. You will have to use the Nuget Package "Websockets.PCL".
I have a Web API project that is running on a server. It is supposed to return PDFs from two different kinds of sources: an actual portable document file (PDF), and a base64 string stored in a database. The trouble I'm having is sending the document back to a client MVC application. The rest of this is the details on everything that's happened and that I've already tried.
I have written code that successfully translates those two formats into C# code and then (back) to PDF form. I have successfully transferred a byte array that was supposed to represent one of those documents, but I can't get it to display in browser (in a new tab by itself). I always get some kind of "cannot be displayed" error.
Recently, I made a way to view the documents on the server side to make sure I can at least get it to do that. It gets the document into the code and creates a FileStreamResult with it that it then returns as an (implicit cast) ActionResult. I got that to return to a server side MVC controller and threw it into a simple return (no view) that displays the PDF just fine in the browser. However, trying to simply go straight to the Web API function simply returns what looks like a JSON representation of a FileStreamResult.
When I try to get that to return properly to my client MVC application, it tells me that "_buffer" can't be directly set. Some error message to the effect that some of the properties being returned and thrown into an object are private and can't be accessed.
The aforementioned byte-array representation of the PDF, when translated to a base64 string, doesn't seem to have the same number of characters as the "_buffer" string returned in the JSON by a FileStreamResult. It's missing about 26k 'A's at the end.
Any ideas about how to get this PDF to return correctly? I can provide code if necessary, but there has to be some known way to return a PDF from a server-side Web API application to a client-side MVC application and display it as a web page in a browser.
P.S. I do know that the "client-side" application isn't technically on the client side. It will also be a server application, but that shouldn't matter in this case. Relative to the Web API server, my MVC application is "client-side".
Code
For getting pdf:
private System.Web.Mvc.ActionResult GetPDF()
{
int bufferSize = 100;
int startIndex = 0;
long retval;
byte[] buffer = new byte[bufferSize];
MemoryStream stream = new MemoryStream();
SqlCommand command;
SqlConnection sqlca;
SqlDataReader reader;
using (sqlca = new SqlConnection(CONNECTION_STRING))
{
command = new SqlCommand((LINQ_TO_GET_FILE).ToString(), sqlca);
sqlca.Open();
reader = command.ExecuteReader(CommandBehavior.SequentialAccess);
try
{
while (reader.Read())
{
do
{
retval = reader.GetBytes(0, startIndex, buffer, 0, bufferSize);
stream.Write(buffer, 0, bufferSize);
startIndex += bufferSize;
} while (retval == bufferSize);
}
}
finally
{
reader.Close();
sqlca.Close();
}
}
stream.Position = 0;
System.Web.Mvc.FileStreamResult fsr = new System.Web.Mvc.FileStreamResult(stream, "application/pdf");
return fsr;
}
API Function that gets from GetPDF:
[AcceptVerbs("GET","POST")]
public System.Web.Mvc.ActionResult getPdf()
{
System.Web.Mvc.ActionResult retVal = GetPDF();
return retVal;
}
For displaying PDF server-side:
public ActionResult getChart()
{
return new PDFController().GetPDF();
}
The code in the MVC application has changed a lot over time. The way it is right now, it doesn't get to the stage where it tries to display in browser. It gets an error before that.
public async Task<ActionResult> get_pdf(args,keys)
{
JObject jObj;
StringBuilder argumentsSB = new StringBuilder();
if (args.Length != 0)
{
argumentsSB.Append("?");
argumentsSB.Append(keys[0]);
argumentsSB.Append("=");
argumentsSB.Append(args[0]);
for (int i = 1; i < args.Length; i += 1)
{
argumentsSB.Append("&");
argumentsSB.Append(keys[i]);
argumentsSB.Append("=");
argumentsSB.Append(args[i]);
}
}
else
{
argumentsSB.Append("");
}
var arguments = argumentsSB.ToString();
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.GetAsync(URL_OF_SERVER+"api/pdf/getPdf/" + arguments).ConfigureAwait(false);
jObj = (JObject)JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result);
}
return jObj.ToObject<ActionResult>();
}
The JSON I get from running the method directly from the Web API controller is:
{
"FileStream":{
"_buffer":"JVBER...NjdENEUxAA...AA==",
"_origin":0,
"_position":0,
"_length":45600,
"_capacity":65536,
"_expandable":true,
"_writable":true,
"_exposable":true,
"_isOpen":true,
"__identity":null},
"ContentType":"application/pdf",
"FileDownloadName":""
}
I shortened "_buffer" because it's ridiculously long.
I currently get the error message below on the return line of get_pdf(args,keys)
Exception Details: Newtonsoft.Json.JsonSerializationException: Could not create an instance of type System.Web.Mvc.ActionResult. Type is an interface or abstract class and cannot be instantiated. Path 'FileStream'.
Back when I used to get a blank pdf reader (the reader was blank. no file), I used this code:
public async Task<ActionResult> get_pdf(args,keys)
{
byte[] retArr;
StringBuilder argumentsSB = new StringBuilder();
if (args.Length != 0)
{
argumentsSB.Append("?");
argumentsSB.Append(keys[0]);
argumentsSB.Append("=");
argumentsSB.Append(args[0]);
for (int i = 1; i < args.Length; i += 1)
{
argumentsSB.Append("&");
argumentsSB.Append(keys[i]);
argumentsSB.Append("=");
argumentsSB.Append(args[i]);
}
}
else
{
argumentsSB.Append("");
}
var arguments = argumentsSB.ToString();
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/pdf"));
var response = await client.GetAsync(URL_OF_SERVER+"api/webservice/" + method + "/" + arguments).ConfigureAwait(false);
retArr = await response.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
}
var x = retArr.Skip(1).Take(y.Length-2).ToArray();
/*Response.Clear();
Response.ClearContent();
Response.ClearHeaders();
Response.ContentType = "application/pdf";
Response.AppendHeader("Content-Disposition", "inline;filename=document.pdf");
Response.BufferOutput = true;
Response.BinaryWrite(x);
Response.Flush();
Response.End();*/
return new FileStreamResult(new MemoryStream(x),MediaTypeNames.Application.Pdf);
}
Commented out is code from some other attempts. When I was using that code, I was returning a byte array from the server. It looked like:
JVBER...NjdENEUx
Some Server side code to return PDF (Web Api).
[HttpGet]
[Route("documents/{docid}")]
public HttpResponseMessage Display(string docid) {
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.BadRequest);
var documents = reader.GetDocument(docid);
if (documents != null && documents.Length == 1) {
var document = documents[0];
docid = document.docid;
byte[] buffer = new byte[0];
//generate pdf document
MemoryStream memoryStream = new MemoryStream();
MyPDFGenerator.New().PrintToStream(document, memoryStream);
//get buffer
buffer = memoryStream.ToArray();
//content length for use in header
var contentLength = buffer.Length;
//200
//successful
var statuscode = HttpStatusCode.OK;
response = Request.CreateResponse(statuscode);
response.Content = new StreamContent(new MemoryStream(buffer));
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
response.Content.Headers.ContentLength = contentLength;
ContentDispositionHeaderValue contentDisposition = null;
if (ContentDispositionHeaderValue.TryParse("inline; filename=" + document.Name + ".pdf", out contentDisposition)) {
response.Content.Headers.ContentDisposition = contentDisposition;
}
} else {
var statuscode = HttpStatusCode.NotFound;
var message = String.Format("Unable to find resource. Resource \"{0}\" may not exist.", docid);
var responseData = responseDataFactory.CreateWithOnlyMetadata(statuscode, message);
response = Request.CreateResponse((HttpStatusCode)responseData.meta.code, responseData);
}
return response;
}
On my a View you could do something like this
<a href="api/documents/1234" target = "_blank" class = "btn btn-success" >View document</a>
which will call the web api and open the PDF document in a new tab in the browser.
Here is how i basically do the same thing but from a MVC controller
// NOTE: Original return type: FileContentResult, Changed to ActionResult to allow for error results
[Route("{docid}/Label")]
public ActionResult Label(Guid docid) {
var timestamp = DateTime.Now;
var shipment = objectFactory.Create<Document>();
if (docid!= Guid.Empty) {
var documents = reader.GetDocuments(docid);
if (documents.Length > 0)
document = documents[0];
MemoryStream memoryStream = new MemoryStream();
var printer = MyPDFGenerator.New();
printer.PrintToStream(document, memoryStream);
Response.AppendHeader("Content-Disposition", "inline; filename=" + timestamp.ToString("yyyyMMddHHmmss") + ".pdf");
return File(memoryStream.ToArray(), "application/pdf");
} else {
return this.RedirectToAction(c => c.Details(id));
}
}
return this.RedirectToAction(c => c.Index(null, null));
}
Hope this helps
I needed to return a pdf file from a .NET core 3.1 web api, and found this excellent article:
https://codeburst.io/download-files-using-web-api-ae1d1025f0a9
Basically, you call:
var bytes = await System.IO.File.ReadAllBytesAsync(pathFileName);
return File(bytes, "application/pdf", Path.GetFileName(pathFileName));
Whole code is:
using Microsoft.AspNetCore.Mvc;
using System.IO;
using Reportman.Drawing;
using Reportman.Reporting;
using System.Text;
using System.Threading.Tasks;
[Route("api/[controller]")]
[ApiController]
public class PdfController : ControllerBase
{
[HttpGet]
[Route("ot/{idOT}")]
public async Task<ActionResult> OT(string idOT)
{
Report rp = new Report();
rp.LoadFromFile("ot-net.rep"); // File created with Reportman designer
rp.ConvertToDotNet();
// FixReport
rp.AsyncExecution = false;
PrintOutPDF printpdf = new PrintOutPDF();
// Perform the conversion from one encoding to the other.
byte[] unicodeBytes = Encoding.Convert(Encoding.ASCII, Encoding.Unicode, Encoding.ASCII.GetBytes($"Orden de trabajo {idOT}"));
string unicodeString = new string(Encoding.Unicode.GetChars(unicodeBytes));
// todo: convert to unicode
// e = Encoding.GetEncoding(unicodeString);
// System.Diagnostics.Trace.WriteLine(e);
if (rp.Params.Count > 0)
{
rp.Params[0].Value = unicodeString;
}
printpdf.FileName = $"ot-{idOT}.pdf";
printpdf.Compressed = false;
if (printpdf.Print(rp.MetaFile))
{
// Download Files using Web API. Changhui Xu. https://codeburst.io/download-files-using-web-api-ae1d1025f0a9
var bytes = await System.IO.File.ReadAllBytesAsync(printpdf.FileName);
return File(bytes, "application/pdf", Path.GetFileName(printpdf.FileName));
}
return null;
}
Call to this API looks like: https://localhost:44387/api/pdf/ot/7
Reportman is a pdf generator you can found at:
https://reportman.sourceforge.io/
Enjoy!
Problem:
I have a Java spring rest service to upload a file (large size).
I want use a .NET httpClient (or other .net client) to call upload service.
Questions:
It seems that best option to send large file is multi-part file, what's about interoperability ?
If it weren't possible, what is the best alternative ?
Thank you!
This is the answer:
I can send a file with multipart attachment from c# client to Java JAX Rest Webservice.
try
{
using (
var client = new HttpClient())
using (var form = new MultipartFormDataContent())
{
using (var stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) {
using (var fileContent = new StreamContent(stream)) {
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") {FileName = fileName, DispositionType = DispositionTypeNames.Attachment, Name = "fileData"};
form.Add(fileContent);
// only for test purposes, for stable environment, use ApiRequest class.
response = client.PostAsync(url, form).Result;
}
}
}
return response.RequestMessage != null ? response.ReasonPhrase : null;
}
catch (Exception ex)
{
TraceManager.TraceError("Post Asyn Request to " + url + " \n" + ex.Message, ex);
throw;
}
HTTP is a standard that is independent of OS platforms and programming languages, so you shouldn't have any problems with interoperability in case your .net client complies with the standards.
java spring boot
#RequestMapping(value="/upload", method=RequestMethod.POST)
public #ResponseBody String upload(#RequestParam("FileParam") MultipartFile file){
InputStream fromClient=file.getInputStream();
...do stuff with the database/ process the input file...
c#
HttpClient client = new HttpClient();
MultipartFormDataContent form = new MultipartFormDataContent();
FileInfo file = new FileInfo(#"<file path>");
form.Add(new StreamContent(file.OpenRead()),"FileParam",file.Name);
HttpResponseMessage response = await client.PostAsync("http://<host>:<port>/upload", form);
Console.WriteLine(response.StatusCode);
Console.WriteLine(response.ReasonPhrase);
Console.WriteLine(response.ToString());
Console.WriteLine(Encoding.ASCII.GetString(await response.Content.ReadAsByteArrayAsync()));