I have the following controller method which gets a PNG from a web api.
public async Task<ActionResult> RealTimeUpdate(string fundName)
{
string docPath = ConfigurationManager.AppSettings["RealTimeUpdate"].Replace("{fundname}",fundName).ToString();
docPath = docPath.Replace("\\\\", "\\");
docPath = docPath.Replace("\"", "");
string url = ServiceUrl + "api/RealTime/" + fundName;
HttpResponseMessage response = await client.GetAsync(url);
if (response.IsSuccessStatusCode)
{
var dataStream = response.Content.ReadAsStringAsync().Result;
if (dataStream == null)
return HttpNotFound();
var _buffer = JsonConvert.DeserializeAnonymousType(dataStream, new { _buffer = (byte[])null })._buffer;
// If user decides to save the file, this will help...
//Response.AddHeader("content-disposition", "filename=" + Path.GetFileName(path));
return File(_buffer, "application/png");
}
return View("Error");
}
I call it like this:
Real Time Update
As you can see, I have target="_blank", however, instead of displaying the image in a new tab, it downloads it to my documents folder. How can I get it to display in a tab?
You need a ImageController to render that.
once you have a controller you can render as follows:
public class ImageController{
public ActionResult ShowImage(string path)
{
return File(path);
}
}
in your views:
<img src="#Url.Action("Render","Image", new {id =1 // or path })" />
this answer was taken from https://stackoverflow.com/a/16142574/5586581
Related
The retrieval and image conversion from byte to image is working great
API CODE:
[HttpGet]
public HttpResponseMessage MemberImage(string employeeId)
{
IMemberProcedures storedProcedure = new StoredProcedure();
IValidation validation = new CommonRepository();
RequestModel request = SQL.Read(out List<MemberDetail> members, storedProcedure.SAMPLESTOREDPROCEDURE("::1", employeeId));
byte[] imgData = members[0].Picture;
MemoryStream ms = new MemoryStream(imgData);
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StreamContent(ms);
response.Content.Headers.ContentType = new
MediaTypeHeaderValue("image/png");
return response;
}
Trying this in postman returns a fully converted image
Now I wanted to display that image to my Web and this is what I have tried;
WEB CODE:
[HttpGet]
public ActionResult MemberImage(string id)
{
IGetInterface Ip = new IpHelper();
HttpResponseMessage image = API.GetResponse($"api/QMS/MemberImage?employeeId={id}");
var foo = image.Content.ReadAsStringAsync().Result;
return File(Enumerable.Range(0, foo.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(foo.Substring(x, 2), 16))
.ToArray(), "image/png");
}
This triggers an error of Unsupported Media and I dont think I am doing the right way of displaying the image from web controller to my view.
Is there any other way on displaying image result of API to WEB?
Finally after several retries I got it working by using ReadAsByteArrayAsync().
[HttpGet]
public ActionResult MemberImage(string id)
{
IGetInterface Ip = new IpHelper();
HttpResponseMessage image = API.GetResponse($"api/QMS/MemberImage?employeeId={id}");
byte[] foo = image.Content.ReadAsByteArrayAsync().Result;
return File(foo, "image/png");
}
Display it to view by doing this;
<img src='#Url.Action("MemberImage", new { id = Model.Member.EmployeeNumber })'>
I wanted to print header data which are dynamic and will come from controller.
So how can I display that dynamic data in header using Rotativa pdf.
My header data include Name, Address, Contact info and other additional information, which are dynamic and generated from controller side.
I have created pdf with static header as below by using html page
string header = Server.MapPath("~/Static/NewFolder/PrintHeader.html");
string footer = Server.MapPath("~/Static/NewFolder/PrintFooter.html");
string customSwitches = string.Format("--header-html \"{0}\" " +
"--header-spacing \"0\" " +
"--footer-html \"{1}\" " +
"--footer-spacing \"10\" " +
"--footer-font-size \"10\" " +
"--header-font-size \"10\" ", header, footer);
return new ViewAsPdf("SchedulePrintPdf", modelData)
{
CustomSwitches = customSwitches,
PageOrientation = Orientation.Portrait,
PageMargins = { Top = 20, Bottom = 22 },
SaveOnServerPath = filePath, FileName = Path.GetFileName(fileName)
};
This is working well with Static header.
Now I need the header text will go from this controller dynamically.
I had a similar specification once and realized it with an extra View for Printing.
There you can get additional data from the controller and include a special CSS style.
When you use bootstrap, consider that the resolution used for PDF-printing is very small, so you have to use the col-xs-* classes.
In my case the Print-View was called ResultPrint.cshtml and in the Controller I had this function:
public ActionResult GeneratePDF(int id)
{
InputPrintModel model = db.InputPrintModel.Find(id);
if (model == null)
{
return HttpNotFound();
}
try
{
return new ViewAsPdf("ResultPrint", model);
}
catch (Exception ex)
{
// Error Dialog + Logging
return View("Result", model);
}
}
which was called in my Result.cshtml like this:
#Html.ActionLink("Generate PDF", "GeneratePDF", new { id = Model.Id })
EDIT
When you look at this answer https://stackoverflow.com/a/26544977/2660864 you can see, that you can use .cshtml files in your CustomActions (I did not test this code)
public ActionResult ViewPDF()
{
string cusomtSwitches = string.Format("--print-media-type --allow {0} --footer-html {0} --footer-spacing -10",
Url.Action("Footer", "Document", new { area = ""}, "https"));
return new ViewAsPdf("MyPDF.cshtml", model)
{
FileName = "MyPDF.pdf",
CustomSwitches = customSwitches
};
}
[AllowAnonymous]
public ActionResult Footer()
{
// get custom data for view
return View(model);
}
have the following image, from a database...
<img src="#Url.Action("GetLogo", "Logo", new { ID = 16})" />
And the controller....
public FileContentResult GetLogo(int ID)
{
var GetImage = (from x in repository.GetClientLogo
where x.ClientID == ClientID
select x).FirstOrDefault();
ClientLogo clientLogo = GetImage;
return File(clientLogo.ImageData, clientLogo.ImageMimeType);
}
This all works fine until there is no database record - if this is the case, then I want to return a default image (example <img src="../Images/NoLogo.jpg" />), but I'm having difficulties as the above controller returns FileContentResult.
Any help would be appreciated.
public FileContentResult GetLogo(int ID)
{
var GetImage = (from x in repository.GetClientLogo
where x.ClientID == ClientID
select x).FirstOrDefault();
if (GetImage == null)
{
return File(Server.MapPath("/Images/NoLogo.jpg"), "image/jpeg");
}
ClientLogo clientLogo = GetImage;
return File(clientLogo.ImageData, clientLogo.ImageMimeType);
}
Just return NoLogo file when you can't find image for client
I have Webpage with table of objects.
One of my object properties is the file path, this file is locate in the same network. What i want to do is wrap this file path under link (for example Download) and after the user will click on this link the file will download into the user machine.
so inside my table:
#foreach (var item in Model)
{
<tr>
<th width ="150"><p><b>Download</b></p></th>
<td width="1000">#item.fileName</td>
<td width="50">#item.fileSize</td>
<td bgcolor="#cccccc">#item.date<td>
</tr>
}
</table>
I created this download link:
<th width ="150"><p><b>Download</b></p></th>
I want this download link to wrap my file path and click on thie link will lean to my controller:
public FileResult Download(string file)
{
byte[] fileBytes = System.IO.File.ReadAllBytes(file);
}
What i need to add to my code in order to acheive that ?
Return FileContentResult from your action.
public FileResult Download(string file)
{
byte[] fileBytes = System.IO.File.ReadAllBytes(file);
var response = new FileContentResult(fileBytes, "application/octet-stream");
response.FileDownloadName = "loremIpsum.pdf";
return response;
}
And the download link,
Download
This link will make a get request to your Download action with parameter fileName.
EDIT: for not found files you can,
public ActionResult Download(string file)
{
if (!System.IO.File.Exists(file))
{
return HttpNotFound();
}
var fileBytes = System.IO.File.ReadAllBytes(file);
var response = new FileContentResult(fileBytes, "application/octet-stream")
{
FileDownloadName = "loremIpsum.pdf"
};
return response;
}
In the view, write:
Download
In the controller, write:
public FileResult DownloadFile(string file)
{
string filename = string.Empty;
Stream stream = ReturnFileStream(file, out filename); //here a backend method returns Stream
return File(stream, "application/force-download", filename);
}
This example works fine for me:
public ActionResult DownloadFile(string file="")
{
file = HostingEnvironment.MapPath("~"+file);
string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
var fileName = Path.GetFileName(file);
return File(file, contentType,fileName);
}
View:
< script >
function SaveImg()
{
var fileName = "/upload/orders/19_1_0.png";
window.location = "/basket/DownloadFile/?file=" + fileName;
}
< /script >
<img class="modal-content" id="modalImage" src="/upload/orders/19_1_0.png" onClick="SaveImg()">
I am using Rotativa tool to display pdf. It works fine with the following code:
public ActionResult PreviewDocument()
{
var htmlContent = Session["html"].ToString();
var model = new PdfInfo { Content = htmlContent, Name = "PDF Doc" };
return new ViewAsPdf(model);
}
I wanted to know the way to download the pdf via browser's "save as" dialog on clicking on a button and not to display in some iframe. "new ViewAsPdf(model)" just returns the pdf data.
Thanks in advance.
You can add additional attributes to the Rotativa call like this:
return new PartialViewAsPdf("PreviewDocument", pdfModel)
{
PageSize = Size.A4,
FileName = "PDF Doc.pdf"
};
And it'll create the file for you. :)
I finally got a way to do this.
Actually rotativa's method "return new ViewAsPdf(model)" returns HttpResponseStream. Where we can hardly do something. But we can modify/alter the response once the action get executed by using custom attribute. We can override OnResultExecuted() method of action filter.
Controller's action
[HttpGet]
[ActionDownload] //here a custom action filter added
public ActionResult DownloadDocument()
{
var htmlContent = "<h1>sachin Kumar</hi>";
var model = new PdfInfo {FtContent = htmlContent, FtName = "Populate Form"};
return new ViewAsPdf(model);
}
Custom Action filter:
public class ActionDownloadAttribute : ActionFilterAttribute
{
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
//Add content-disposition header to response so that browser understand to download as an attachment.
filterContext.HttpContext.Response.AddHeader("content-disposition", "attachment; filename=" + "Report.pdf");
base.OnResultExecuted(filterContext);
}
}
You can use return new ActionAsPdf. No custom attributes or anything else required.
Example: https://github.com/webgio/Rotativa/
public ActionResult PrintPreviewDocument()
{
return new ActionAsPdf("PreviewDocument") { FileName = "PDF Doc.pdf" };
}
public ActionResult PreviewDocument()
{
var htmlContent = Session["html"].ToString();
var model = new PdfInfo { Content = htmlContent, Name = "PDF Doc" };
return View(model);
}