Create Text File in Memory and return it over ajax, possible? - asp.net

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.

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.

Spring MVC to open PDF as the view

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.

ASP.NET show PDF file to user instead of "save as" dialog

My ASP.NET application return PDF file to user using code below
Context.Response.Clear();
Context.Response.ContentType = "application/pdf";
Context.Response.TransmitFile(optionEntityCmd.PathToSave);
Context.Response.End();
This code show Save As browser dialog, is it possible instead of Save As dialog load PDF file directly in browser?
You could append the Content-Disposition header:
Context.Response.AppendHeader(
"Content-Disposition",
"inline; filename=foo.pdf"
);
Is it a dynamically created file? If not, you can just hyperlink or Response.Redirect to it I believe.
I do not know for sure for classic asp.net but using mvc, streaming it to the user does what you want:
MemoryStream stream = PDF.GeneratePDFByStream();
stream.Flush(); //Always catches me out
stream.Position = 0; //Not sure if this is required
return stream;
with
public static MemoryStream GeneratePDFByStream() {
var doc1 = new Document();
//use a variable to let my code fit across the page...
string path = AppDomain.CurrentDomain.BaseDirectory + "PDFs";
MemoryStream stream = new MemoryStream();
PdfWriter writer = PdfWriter.GetInstance(doc1, stream);
writer.CloseStream = false;
// Actual Writing
doc1.Open();
// writing comes here, you will probably just load the PDF in a stream?
doc1.Close();
return stream;
}
And your MVC controller returns something like
return File(GetPDFStream(id), "application/pdf");
So, I know this is not the exact answer you are looking for, but maybe you should try to stream your PDF to the user as it will open it in a new tab as far as I ever tested it.
From the top of my head, you should get something like:
Response.Clear();
Response.ContentType = "application/pdf";
Response.OutputStream.Write( objMemoryStream.ToArray(), 0,
Convert.ToInt32(objMemoryStream.Length));
Response.Flush();
try { Response.End(); } catch{}

How to Download A file stored in SQL DB in Binary Format

I am simply storing uploaded file into a binary field in SQL Server but I also need to allow users to download it with Asp.NET. How can I do that ?
Thanks in advance.
Here's a Microsoft Knowledge Base article on this.
How to retrieve the file from your database depends on the data access technology you use; I will just assume that you have some Byte array data containing the file (e.g. by filling a DataSet and accessing the field) and some string filename.
Response.Clear()
Response.ContentType = "application/octet-stream"
Response.AddHeader("Content-Disposition", "attachment;filename=""" & filename & """")
Response.BinaryWrite(data)
Response.End()
Put the above code in some download.aspx and link to this file. You probably want to pass some query string information to your download.aspx, so that your code knows which file to get from the database.
Read the data into a filestream object with the appropriate extension tacked on to it, and have the user download the resulting file.
You'll want to use the System.IO BinaryWriter object on the filestream to create the file...something like this:
FileStream fs = new FileStream("thisfile.bin", FileMode.Create);
binWriter= new BinaryWriter(fs);
binWriter.Write(varHoldingSqlRetrievedBinaryData);
Add a Generic Handler (.ashx) page to your web site. The ashx code body below demonstrates how to read an arbitrary stream (in this case a PNG file from disk) and write it out in the response:
using System;
using System.Web;
using System.IO;
namespace ASHXTest
{
public class GetLetter : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
// Get letter parameter from query string.
string fileName = context.Request.MapPath(string.Format("{0}.png",
context.Request.QueryString["letter"]));
// Load file from disk/database/ether.
FileStream stream = new FileStream(fileName, FileMode.Open,
FileAccess.Read);
byte[] buffer = new byte[stream.Length];
stream.Read(buffer, 0, buffer.Length);
stream.Close();
// Write response headers and content.
context.Response.ContentType = "image/png";
context.Response.OutputStream.Write(buffer, 0, buffer.Length);
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
If desired, you can also set the Content-Disposition header as demonstrated in Heinzi's answer:
context.Response.AddHeader("Content-Disposition",
"attachment;filename=\"letter.png\"");

ASP.NET Return image from .aspx link

Is it possible to output an image (or any file type) to a download link when a user clicks on a link from another ASP.NET page?
I have the file name and byte[].
Get File
...where getfile returns the file instead of going to the getfile.aspx page.
You would want .ashx for that really ;)
public class ImageHandler : IHttpHandler
{
public bool IsReusable { get { return true; } }
public void ProcessRequest(HttpContext ctx)
{
var myImage = GetImageSomeHow();
ctx.Response.ContentType = "image/png";
ctx.Response.OutputStream.Write(myImage);
}
}
How to Create Text Image on the fly with ASP.NET
Something like this:
string Path = Server.MapPath(Request.ApplicationPath + "\image.jpg");
Bitmap bmp = CreateThumbnail(Path,Size,Size);
Response.ContentType = "image/jpeg";
bmp.Save(Response.OutputStream,System.Drawing.Imaging.ImageFormat.Jpeg);
bmp.Dispose();
Here is how I have done this in the past:
Response.Clear();
Response.Buffer = true;
Response.AddHeader("Content-Disposition", string.Format("inline;filename=\"{0}.pdf\"",Guid.NewGuid()));
Response.ContentType = #"application/pdf";
Response.WriteFile(path);
Yeah, you have to clear the response completely and replace it with the image byte data as a string, and you need to make sure to set the response header for content-type according to the type of image
Yes, this is possible. There are two parts of the Response object you need to set: the Content-Type and the HTTP Header. The MSDN documentation has the details on the response object but the main concept is pretty simple. Just set the code to something like this (for a Word doc).
Response.ContentType="application/ms-word";
Response.AddHeader("content-disposition", "attachment; filename=download.doc");
There is a more complete example here
the codebehind code for getfile.aspx has to have a content-type and the browser will know that it is an image or a unknown file and will let you save it.
In asp.net you can set the ContentType by using the Response object, i.e.
Response.ContentType = "image/GIF"
Here you have a tutorial for dynamically generated image
ashx...
public class ImageHandler : IHttpHandler
{
public void ProcessRequest(HttpContext ctx)
{
string path = ".....jpg";
byte[] imgBytes = File.ReadAllBytes(path);
if (imgBytes.Length > 0)
{
ctx.Response.ContentType = "image/jpeg";
ctx.Response.BinaryWrite(imgBytes);
}
}
public bool IsReusable
{
get {return false;}
}
}

Resources