How do I provide security in the aspx file downloads? - asp.net

I have web form project, example my link is www.qweqwe.com/setup.exe
if i can write url "www.qweqwe.com/setup.exe" file is downloading automatically.
I don't want this, I need session for download this. I musn't change file name, when session["scr"] is "Ok" than i must let.
(I will use ClickOnce but i don't want can be download from everypeople)
Thanks in advance to everyone

//First check for Session Variable
if(Session["scr"]!=null)
{
//Now if you want file only downloaded by only some specific person then
if(Session["scr"].ToString()=="You Specific Session value")
{
//Here Your File download code
}
}

Build a Generic Handler for downloading files (ASHX).
In the ProcessRequest method you can check the session and serve the file. Here is an example:
public class Download : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
string file = "setup.exe";
if (File.Exists(context.Server.MapPath(file)) && Session["scr"].ToString() == "Ok")
{
context.Response.Clear();
context.Response.ContentType = "application/octet-stream";
context.Response.AddHeader("content-disposition", "attachment;filename=" + Path.GetFileName(file));
context.Response.WriteFile(context.Server.MapPath(file));
context.Response.End();
}
else
{
context.Response.ContentType = "text/plain";
context.Response.Write("File cannot be found!");
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
Don't forget to remove the MIME for the exe file in your IIS so nobody can download it, directly.

Related

Web Api - How to detect when a response has finished being sent

In a web api method I am generating a file and then streaming it to the response like so
public async Task<HttpResponseMessage> GetFile() {
FileInfo file = generateFile();
var msg = Request.CreateResponse(HttpStatusCode.OK);
msg.Content = new StreamContent(file.OpenRead());
msg.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
msg.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") {FileName = file.Name};
return msg;
}
because this a generated file I want to delete it after the response has finished streaming but I can't seem to find a hook in the pipeline for this.
I suppose that I can put a reference to the file in a static and set up a custom MessageHandler that pulls values out of this same static variable and deletes. However, this seems like it can't possibly be right both because of the use of a static (when this should all be per-request) and because I'd have to register a separate route.
I've seen this question but it seems to not really have much of a useful response.
Nice scenario!...the problem with using message handlers is that response writing happens at the host layers and below message handlers layer, so they are not ideal...
Following is an example of how you could do it:
msg.Content = new CustomStreamContent(generatedFilePath);
public class CustomStreamContent : StreamContent
{
string filePath;
public CustomStreamContent(string filePath)
: this(File.OpenRead(filePath))
{
this.filePath = filePath;
}
private CustomStreamContent(Stream fileStream)
: base(content: fileStream)
{
}
protected override void Dispose(bool disposing)
{
//close the file stream
base.Dispose(disposing);
try
{
File.Delete(this.filePath);
}
catch (Exception ex)
{
//log this exception somewhere so that you know something bad happened
}
}
}
By the way, are you generating this file because you are converting some data into PDF. If yes, then I think you could use PushStreamContent for this purpose by directly writing the converted data into the response stream. This way you need not generate a file first and then worry about deleting it later.
We performed same action in WebAPI. I needed to delete file just after it downloaded form server.
We can create custom response message class. It takes file path as parameter and delete it once its transmitted.
public class FileResponseMessage : HttpResponseMessage
{
private readonly string _filePath;
public FileHttpResponseMessage(string filePath)
{
this._filePath= filePath;
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
Content.Dispose();
File.Delete(_filePath);
}
}
Use this class as below code and it will delete your file once it will be written on response stream.
var response = new FileResponseMessage(filePath);
response.StatusCode = HttpStatusCode.OK;
response.Content = new StreamContent(new FileStream(filePath, FileMode.Open, FileAccess.Read));
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "MyReport.pdf"
};
return response;

write source files to output in custom asp.net server control

I am writing own server-side control.I need to use some images in this control.How can I write to output image file [or any other file] and then access it?
protected override void RenderContents(HtmlTextWriter output)
{
.......
output.Write("some file");
string endResult = "<img src= how to access this file? />"
output.Write(endResult);
}
Option 1: Embed It Directly
You can embed images (and other files) directly into webpages using a data URI. Something like:
protected override void RenderContents(HtmlTextWriter output)
{
............
byte[] rawImgData = []; //add your data here, maybe from a FileStream
String imgMimeType = "[img mime type, eg image/png]";
String encodedImgData = Convert.ToBase64String(rawImageData);
output.Write(String.Format("<img src=\"data:{0},{1}\" />", imageMimeType, encodedImageData))
}
As outlined in the link, this approach has lots of disadvantages. If you'll be serving the same images with every request to your control, you should really use static files.
Option 2: Save to the server and map it
Assuming your IIS worker account (normally called IUSR) has write access to some location on the server, you can save it with Server.MapPath and send the actual link out.
protected override void RenderContents(HtmlTextWriter output)
{
............
byte[] rawImgData = []; //add your data here, maybe from a FileStream
FileStream fileStream = System.IO.File.Create(Server.MapPath(virtualPath))
fileStream.Write(rawImgData, 0, rawImgData.Length)
fileStream.Close()
output.Write(String.Format("<img src=\"{0}\" />", virtualPath))
}
For repetitive requests, this definitely the best option.
Option 3: Store it in memory and serve via a second page
You can store the raw data in Session (or another temporary in-memory storage of your choice), send a link with an identifier, and server it from another page. Something like:
protected override void RenderContents(HtmlTextWriter output)
{
............
byte[] rawImgData = []; //add your data here, maybe from a FileStream
Session["MyImgTempStorage"] = rawImgData;
output.Write("<img src=\"ServeImgTempStorage.ashx?file=MyImgTempStorage\");
}
and make a generic handler called ServeImgTempStorage.ashx like this:
public class ServeImgTempStorage : System.Web.IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
string fileKey = context.Request.QueryString("file");
if (string.IsNullOrEmpty(fileKey)) {
return;
}
byte[] rawData = context.Session(fileKey);
context.Response.Write(rawData);
context.Response.ContentType = "[your mime type. you can force a download with attachment;]";
context.Response.End();
}
public bool IsReusable {
get { return false; }
}
}
You'll need to make sure you use session unique identifiers for every file served in this way, or you will overwrite data.
NOTE: My C# syntax may be off, I normally write in VB.

.ashx HTTP handler unable to write image from network share to HTTP response

I am trying to write an HTTP handler in C# that loads images from a network drive and writes them to the HTTP response. This is currently not working for me as I keep getting HTTP 302 responses which results in the broken file image being displayed. Below is my HTTP handler. Access permissions have been set so anonymous users have read access to the share but ideally this will not be permanent.
public class SecCamImage : IHttpHandler, IRequiresSessionState
{
public void ProcessRequest(HttpContext context)
{
Configuration config = WebConfigurationManager.OpenWebConfiguration("~/Web.Config");
KeyValueConfigurationElement setting = null;
if(config.AppSettings.Settings.Count > 0)
{
setting = config.AppSettings.Settings["CameraBaseURL"];
}
if(setting != null)
{
string baseURL = setting.Value;
string location = context.Request["location"].ToString();
string camera = context.Request["camera"].ToString();
string image = context.Request["image"].ToString();
if (!(string.Compare(image, "no-image.jpg", true) == 0))
{
if (!string.IsNullOrEmpty(location) && !string.IsNullOrEmpty(camera) && !string.IsNullOrEmpty(image))
{
string fullPath = string.Format(baseURL, location, camera, image);
System.IO.FileInfo imageFile = new System.IO.FileInfo(fullPath);
if (imageFile.Exists)
{
if (context.User.Identity.IsAuthenticated)
{
context.Response.ContentType = "image/jpeg";
context.Response.WriteFile(imageFile.FullName);
context.Response.End();
}
}
}
}
else
{
context.Response.ContentType = "image/jpeg";
context.Response.WriteFile(image);
context.Response.End();
}
}
}
public bool IsReusable
{
get { return false; }
}
}
The URL stored in the config file is structured like this:-
\\\\host\\directory\\{0}\\{1}\\{2}
{0} and {1} are directories and {2} is the file.
I managed to get this working by adding a Virtual Directory to our Website on IIS. The .ashx handler now references the Virutal Directory and not the directory on the network drive.

How to use FilePathResult.WriteFile?

Background
I have a secured folder containing secret report files (in pdf format). Each file corresponds to a single user.
My site is developed using Asp.net MVC 3 Razor.
When a user navigate to http://mydomain.com/UserProfile/Report, it invokes the GET-handling action method Report and return a view with a submit button Download Report.
When the user click the button, it invokes the POST-handling action method. Verification will be done in this action method. When the verification is successfully passed, the action method returns the requested file.
Question
Could you give me an example how to implement the POST-handling action method?
Here is the skeleton:
[HttpPost]
public ActionResult Report(/*any parameter I don't know*/)
{
if(!IsAuthenticated())
return RedirectToActionLink("SomeActionMethod","SomeController");
else
{
// what should I do here?
// Asssume my secret folder is d:\mydomain.com\secret and the public folder is d:\mydomain.com\httpdoc
}
}
Here is how you can return a file back to the client:
public FileContentResult Report(/*any parameter I don't know*/)
{
if(!IsAuthenticated())
return RedirectToActionLink("SomeActionMethod","SomeController");
else
{
// Read the file from your location into a byte array named content
Response.ContentType = "application/pdf";
return new FileContentResult(content, "application/pdf");
}
}
You can use the File method to return a FileContentResult
[HttpPost]
public FileContentResult Report()
{
if(!IsAuthenticated())
return RedirectToActionLink("SomeActionMethod","SomeController");
else
{
string path = #"d:\mydomain.com\secret\" + fileName;
return File(path, "application/pdf"); ////
}
}

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