Spring MVC to open PDF as the view - spring-mvc

Which is the appropriate View class to render existing PDF? AbstractView?
I am fetching PDF via a webservice ,so I'm not looking to subclass AbstractPdfView to render PDF.
I'd like to stay with the Spring controller classes which return a ModelAndView which means writing my own subclass of AbstractView to just write the PDF to a ServletOutputStream. Any other built in support available in Spring MVC?
Thanks

I agree with #Biju Kunjummen's answer but using iText would be also nice to generate the PDF.
here is the code snippet of the controller method.
#RequestMapping(value = "/common/reportgenerator/generatePDF")
public void generatePdf(HttpServletRequest req,HttpServletResponse res)
{
res.setContentType("text/html;charset=UTF-8");
ServletOutputStream outStream=null;
try
{
String calledFrom = req.getHeader("referer");
calledFrom=req.getRequestURL().substring(0,req.getRequestURL().lastIndexOf("/"))+"/ReportGenerator.egp";
calledFrom += "?isPdf=yes&"+req.getQueryString();
System.out.println(calledFrom+"?isPdf=yes&"+req.getQueryString());
InputStream input = new URL(calledFrom).openStream();
StringWriter writer = new StringWriter();
CopyUtils.copy(input, writer);
//System.out.println(writer.toString());
res.setContentType("application/pdf");
res.setHeader("Content-Disposition", "attachment;filename=report.pdf");
outStream = res.getOutputStream();
ITextRenderer renderer = new ITextRenderer();
renderer.setDocument(calledFrom);
renderer.layout();
renderer.createPDF(outStream);
}
catch (Exception e)
{
new AbcException(e,exceptionHandlerService);
}
finally
{
try
{
outStream.flush();
outStream.close();
}
catch(Exception ex)
{
new AbcException(ex,exceptionHandlerService);
}
}
}
Hope this helps you. Cheers.

I think the best way is to simply stream it out using HttpServletResponse:
OutputStream out = response.getOutputStream();
out.write(..); //buffer and write..

There is no such class.
You have to manually write that file.
Please see answer here:
Display the PDF file stored on the webserver on Browser new window using Spring MVC
I have changed that code to:
// get absolute path of the application
ServletContext context = request.getSession().getServletContext();
String appPath = context.getRealPath("/");
// construct the complete absolute path of the file
String fullPath = appPath + "WEB-INF/pdfs/201507.pdf";
Also, see the answer for not downloading the pdf
and putting the inputStream in the finally block.

Related

How do I write an image's MemoryStream to the page body?

I'm converting ASP.NET WebForms code to ASP.NET Core Razor pages which is new to me. I'm trying to retrieve an image MemoryStream from a business class (based on SixLabors awesome ImageSharp) and have the page render the JPEG -- no HTML, just the image. I intend to use this page elsewhere as an <img> src, like <img src="Render?imageID=42&mode=invert" />
In Render.cshtml.cs:
public class RenderModel : PageModel
{
public void OnGet()
{
//snip
Stream stream = new MemoryStream();
using (Image image1 = Image.Load(imagePath))
{
SixLabors.ImageSharp.Formats.Jpeg.JpegEncoder encoder = new SixLabors.ImageSharp.Formats.Jpeg.JpegEncoder();
encoder.Quality = 75;
image1.Save(stream, encoder);
//image.Save("/temp/xxx.jpg", encoder); //test to see image. it works
}
Response.Clear();
//Response.Headers.ContentLength = stream.Length;
Response.ContentType = "image/jpeg";
Response.Body = stream;
}
}
...but this is not working, I get:
System.InvalidOperationException: Response Content-Length mismatch: too few bytes written (0 of 135408).
135408 is the stream.Length.
I'm probably not doing this correctly in the ASP.NET Core/Razor way. Can anyone set me straight as to how to do this? Thanks!
EDIT: commenting out the Headers.ContentLength fixes the error. But now I get a broken-image icon in the browser. Closer...
You need to write to the Response.Body isntead of replacing it.
stream.Seek(0, SeekOrigin.Begin);
await stream.CopyToAsync(Response.Body);
await Response.Body.FlushAsync();
I think Razor pages are intented to return html content.
However it seems to be possible to return different types of result in OnGet e.g. you could return a new FileContentReset (FileStreamResult seems to have issues with contentlength)
// read as bytes
public FileContentResult OnGet()
{
var image = System.IO.File.ReadAllBytes(#"c:\temp\myimage.jpeg");
return new FileContentResult(image.ToArray(), "image/jpeg");
}
// example if image comes from stream
public FileContentResult OnGet()
{
using var imageStr = System.IO.File.Open(#"c:\temp\myimage.jpeg", FileMode.Open);
using var memStr = new MemoryStream();
imageStr.CopyTo(memStr);
return new FileContentResult(memStr.ToArray(), "image/jpeg");
}
Even better maybe it to not use a Razor page and to add a MVC controller to return the result.

Unable to load an html file (from local file system) using JxBrowser

Using JavaFX and Eclipse IDE, I have used the sample app from Teamdev for loading a sample file (notifications.html from my file system) but I keep getting the page not found/DNS error.
The file in question, notifications.html, is right there in the same package as the source file that invokes it as shown in the snippet below:
Scene scene = new Scene(new BorderPane(view), 700, 500);
primaryStage.setScene(scene);
primaryStage.show();
browser.loadURL("notifications.html");
I think my issue is composing the fully qualified path and since I'm using a Mac, it is not clear to me how to do this. I have tried:
browser.loadURL("Users/myusername/Documents/workspace/jxBrowser/src/application/notifications.html");
However it did not work.
You need to use loadHtml() instead loadUrl() suppose loadHtml goes to network and you try to download url from file on your pc. Read html from filesystem to String and pass it to loadHtml() method.
InputStream urlStream = getClass().getResourceAsStream("/notifications.html");
String html = null;
try (BufferedReader urlReader = new BufferedReader(new InputStreamReader (urlStream))) {
StringBuilder builder = new StringBuilder();
String row;
while ((row = urlReader.readLine()) != null) {
builder.append(row);
}
html = builder.toString();
} catch (IOException e) {
throw new RuntimeException(e);
}
browser.loadHTML(html);
for this code your html file must be in resources folder of your project

Modify dynamically a rdlc report (c#)

I have a font stored in a database, and I have to set all my fileds with that font.
I set bind my report like this :
FormBudgReelReport form = new FormBudgReelReport();
form.Viewer.LocalReport.ReportEmbeddedResource = _NomRessourceRpt;
form.Viewer.LocalReport.DataSources.Add(source);
form.ShowDialog();
If I could load my rdlc as an XmlDocument, I know how to do this, but is there a way to do this?
I can't use a formula like =Parameters!Police.Value because I have a lot of reports to change.
Ok !
I could load my rdlc as a xmlDocument by this code :
Stream st = this.GetType().Assembly.GetManifestResourceStream(_NomRessourceRpt);
// convert stream to string
StreamReader reader = new StreamReader(st);
string reportDef = reader.ReadToEnd();
XmlDocument document = new XmlDocument();
document.LoadXml(reportDef);
Thanks for the help :)
If I could load my rdlc as an XmlDocument, I know how to do this, but is there a way to do this?
In the Solution Explorer you can right-click the .rdlc file and select <Open With...> to choose the editor .
Update:
I am seeking for a way to load my rdlc in a xmlDocument object and then edit xml nodes in runtime.
The following code snippet helps you to load the .rdlc report file from the resources folder to an Xml document:
using System;
using System.Windows.Forms;
using System.Xml;
using System.IO;
using System.Resources;
private void LoadRDLCFromResources()
{
//Declare variables
XmlDocument objXmlDocument = new XmlDocument();
Byte[] byteArray;
Stream objStream = null;
ResourceManager resourceManager = null;
try
{
// Initialize ResourceManager object
resourceManager = new ResourceManager("your_namespace_name.Properties.Resources", GetType().Assembly);
if (resourceManager != null)
{
//Load the resource file "Sample.rdlc" into ByteArray
byteArray = (Byte[])resourceManager.GetObject("Sample");
if (byteArray != null)
{
//Load this bytearray into MemoryStream
objStream = new MemoryStream(byteArray);
if (byteArray.Length > 0)
{
//Load this stream object into XML document and
//thus you get the rdlc file loaded as an XML
//document.
objXmlDocument.Load(objStream);
// Code for using this xml document as per your use
}
}
}
}
//MissingManifestResourceException is an exception thrown when the resource manager fails to initialize appropriately. In such case, please check the namespace name.
catch (MissingManifestResourceException ex)
{
MessageBox.Show("Exception -> " + ex.Message,
"Sample Demo", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
catch (Exception ex)
{
MessageBox.Show("Exception -> " + ex.Message,
"Sample Demo", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
// Clear the objects in finally block. This is required for memory management issues.
// If xml document is not required further then clear it in the following manner
if (objXmlDocument != null)
{
objXmlDocument.DocumentElement.RemoveAllAttributes();
objXmlDocument.DocumentElement.RemoveAll();
objXmlDocument.RemoveAll();
}
//Clear the memory stream object
if (objStream != null)
{
objStream.Flush();
objStream.Close();
objStream.Dispose();
}
// Clear resource manager
resourceManager.ReleaseAllResources();
}
}
Source: How to load a rdlc file from resources folder into an XML document dynamically?

Trying to get DHL shipping rates using ASP.Net but DHL's docs/samples are J2EE-geared. Anyone doing this in .Net that can provide some direction?

I'd like to get DHL shipping rates either per transaction or in batch all at once (to store in a table for later use) from an ASP.Net e-commerce application that ships product internationally, but after downloading their J2EE-based toolkit (https://xmlpi-ea.dhl.com) and reviewing the documentation & samples, I'm not quite sure how to do it in .Net. If anyone has experience with getting DHL shipping rates, I'd appreciate a point in the right direction using .Net. as I don't know Java.
Edit
Just found out the servlet is not discoverable, which means I cannot WSDL it to get a proxy class and will have to rely on tons of their XML samples to build my own client. Anyone done this in .NET already?
Looks like they have web services that you can use.
http://www.dhl-usa.com/en/express/resource_center/integrated_shipping_solutions.html
Sorry to be late. I just finished developing an integration and I give you here the way.
First you have to use xsd2code++ because the XSD.EXE from Microsoft doesn't work. Don't ask me why but it doesn't find the import included in the XSD file or maybe I didn't dig enough why and once I tried xsd2code++ it was a breeze to just right click the XSD in Visual Studio and use the option there.
Once you have your XSD converted to classes you consume it with the 3 methods bellow. See the 2 following lines of code that use the methods. Don't forget to add the necessary usings for XDocument.
Once you register on DHL web site you can download the DHL Toolkit PI which contains the folder XSD where all the XSD files are located.
NOTE : An alternative to Xsd2Code++ is Xsd2code on CodePlex : XSD2CODE hurry up because CodePlex is closing
string Request = XDocument.Parse(SerializeToXML(Quote)).ToString();
string Response = XDocument.Parse(SendRequest(Request)).ToString();
if (Response.IndexOf("DCTResponse") != -1)
DCTResponse = DeserializeFromXML<DHL.Response.DCTResponse>(Response);
else
DCTErrorResponse = DeserializeFromXML<DHL.Response.ErrorResponse>(Response);
public static string SendRequest(string XML)
{
string Response = "";
try
{
HttpWebRequest myReq = null;
myReq = WebRequest.Create(Properties.Settings.Default.DHLURL) as HttpWebRequest;
myReq.ContentType = "application/x-www-form-urlencoded";
myReq.Method = "POST";
using (System.IO.Stream stream = myReq.GetRequestStream())
{
byte[] arrBytes = ASCIIEncoding.ASCII.GetBytes(XML);
stream.Write(arrBytes, 0, arrBytes.Length);
stream.Close();
}
WebResponse myRes = myReq.GetResponse();
System.IO.Stream respStream = myRes.GetResponseStream();
System.IO.StreamReader reader = new System.IO.StreamReader(respStream, System.Text.Encoding.ASCII);
Response = reader.ReadToEnd();
myRes.Close();
myRes = null;
}
catch (Exception ex)
{
Response = ex.ToString();
}
return Response;
}
public static string SerializeToXML<T>(T toSerialize)
{
string Result = "";
XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); ns.Add("", "");
using (TextWriter tw = new StringWriter())
{
using (XmlWriter writer = XmlWriter.Create(tw, new XmlWriterSettings { OmitXmlDeclaration = true }))
{
new XmlSerializer(typeof(T)).Serialize(writer, toSerialize, ns);
Result = tw.ToString();
}
}
return Result;
}
public static T DeserializeFromXML<T>(string xml)
{
var serializer = new XmlSerializer(typeof(T));
return (T)serializer.Deserialize(new StringReader(xml));
}
Hope this helps...

Create Text File in Memory and return it over ajax, possible?

I can create a text file easily enough but I want to avoid having to keep the file on the server.
How can I create a text file in memory and return it over ajax so the file itself is returned and no file is kept on server? It doesn't need to be ajax but I want to avoid a postback if at all possible.
You can use below code to download text file in webforms
MemoryStream ms = new MemoryStream();
TextWriter tw = new StreamWriter(ms);
tw.WriteLine("HELLO WORLD!");
tw.WriteLine("I WANT TO SAVE THIS FILE AS A .TXT FILE!");
tw.Flush();
var bytes = ms.GetBuffer();
Response.ClearContent();
Response.AddHeader("Content-Disposition", "attachment; filename=test.txt");
Response.AddHeader("Content-Length", bytes.Length.ToString());
Response.ContentType = "text/plain";
Response.BinaryWrite(bytes);
Vijay's answer is correct if you're using either MVC or WebForms.
About preventing postback, You don't have to use ajax to prevent postback.
If you're using MVC, You just have to use window.location and point it to your action method in js. Something like:
// In your controller:
public class HomeController : Controller
{
public FileResult GetFile2(int id)
{
if (SomeCondition)
{
return null;
}
var fileName = "MyResult.txt";
var content = "Here's the result";
var contentType = "text/plain";
return File(Encoding.ASCII.GetBytes(content), contentType, fileName);
}
// And in your view/js file:
window.location.href = ('/Home/GetFile?id=1');
And if you're using webforms, I think best way is to create a HttpHandler to handle download links. A good tutorial can be found here.

Resources