ASP.NET MVC3: Cant find/access file - asp.net

String DocLocation = System.AppDomain.CurrentDomain.BaseDirectory + "Files/test.pdf";
// or
String DocLocation = Url.Content("~/Files/test.pdf");
var document = new FileStream(DocLocation, FileMode.Open);
var mimeType = "application/pdf";
var fileDownloadName = "download.pdf";
return File(document, mimeType, fileDownloadName);
The first method is UnauthorizedAccessException.
The second method cant find the file.
I am trying to send a file for download. Using full desktop path seems to work.
Also, how would I display PDF in the browser instead (note, still need download option as not all are pdf)?

Try Server.MapPath("~/Files/test.pdf")

File() takes a physical path on disk.
Therefore, you can't use Url.Content, since that returns a relative URL for the browser.
Instead, you need Server.MapPath, which converts an application relative path into a full path on the local disk.

Related

Fortify Cross-site scripting: Persistent issue in Response.Binarywrite

In an existing Asp.Net application, we are using Response.BinaryWrite to render image on an aspx page. This is the required functionality, and below is the C# code-
1. byte[] img = getImage();
2. Response.BinaryWrite(img);
The getImage function reads the image from a folder on server and returns byte array. Fortify scan shows cross-site vulnerability on 2nd line.
I did following validations, but fortify still reports it as cross-site issue -
Validated bytearray to check if the file is of correct format (jpeg or bmp), used this link - Determine file type of an image
Response.BinaryWrite(ValidateFileType(img));
Validated the domain in the file path to check if the file is originating from correct domain.
Is there any specific way to pass the fortify cross-site issue with byte array or can i consider it as false positive?
Had to use a workaround to resolve this, below is the old and new code -
Old Code -
1. byte[] byteImage = getImage();
2. Response.BinaryWrite(byteImage);
New Code (Replaced 2nd line in old code with below block) -
byte[] byteImage = getImage();
var msIn = new MemoryStream(byteImage);
System.Drawing.Image img = System.Drawing.Image.FromStream(msIn);
var msOut = new MemoryStream();
img.Save(msOut, img.RawFormat);
Response.BinaryWrite(msOut.ToArray());
msIn.Dispose();
msOut.Dispose();
Response.Flush();
So, basically converting the byteArray to an Image object, and then writing the image object back to the Response.BinaryWrite stream resolved this, and it passed through Fortify scan.
If anyone is looking for a solution, this might help.

Extracting Windows File Properties with http link

I am working on this problem and the proposed solution works for me.
However, now I need to make this work in my actual application which is an AWS Beanstalk .NET web application. My beanstalk application knows the url source of the picture. Knowing the url, I can get a stream and process the file (by creating a byte array and even a Bitmap object).
However, it seems that to get the file properties as mentioned above (such as the camera type or painting application that created the file), I really need a local file because that is the expected input argument.
This is a problem for me. I know the http link, I know the bytes but I have no such thing as a file path.
How can I solve this? I need the windows file properties.
If I understood you correctly, you want to read image metadata from a URL without saving it to a file first, i.e. directly from the Internet.
Here is one way that works for me:
string demoImageUrl = "https://raw.githubusercontent.com/ianare/exif-samples/master/jpg/Canon_40D.jpg";
byte[] imgData = null;
using (var wc = new WebClient())
{
imgData = wc.DownloadData(demoImageUrl);
}
using (var sr = new MemoryStream(imgData, false))
{
BitmapSource image = BitmapFrame.Create(sr);
BitmapMetadata md = (BitmapMetadata)image.Metadata;
string comment = md.Comment;
string title = md.Title;
string dateTaken = md.DateTaken;
}
You need to add references to PresentationCore and WindowsBase assemblies and also include the following namespace:
using System.Windows.Media.Imaging;

FileResult not returning proper file type and file name

I have an ASP.NET MVC application with an ActionResult called GenerateReport. I'm trying to return a byte array to save an Excel file. Here are snippets:
var contentType = "application/vnd.ms-excel";
var fileName = "Statistics.xlsx";
...
var fileBytes = package.GetAsByteArray();
return File(fileBytes, contentType, fileName);
When I'm prompted to save the file, it sometimes (but not always) asks what I want to do with "GenerateReport". It's naming the file the same as the ActionResult and it's not giving it a file type. I will request to save it and it will say that it failed to save. I will select Retry and it will save fine. Then, if I rename it to an .xlsx, all of the data is there and correct. I'm using IE9 and Chrome and I haven't noticed it happen in Chrome. Unfortunately, it needs to work in IE9.
Does anyone know why it's not getting my content type and file name sometimes?
Check the response for Content-Encoding. It might be the same issue like here PHP File Serving Script: Unreliable Downloads?

how to load image with relative path in bitmap

i want to upload image int the bitmap object from asp.net, the image is location under
/uploadedimages/sampleimage.jpg
whenever i use below code to load image in bitmap, i gets error saying Parameter not valid.
Bitmap b = new Bitmap("/uploadedimages/sampleimage.jpg") // this path is coming from database holded in variable
i tried to replace the slashes in path to "\" still that does not work.
can anyone tell me what could be the reason for the error and the possible resolution.
Use Server.MapPath. And it's a good practice to use the tilde char ~ to specify the web application root.
Bitmap b = new Bitmap(Server.MapPath("~/uploadedimages/sampleimage.jpg"));
if uploadedimages directory is in your App_Data folder then you should append the App_Data absolute path to your path:
Bitmap b = new Bitmap(Path.Combine(Server.MapPath("~/App_Data"), "/uploadedimages/sampleimage.jpg"));
You can use server.MapPath, pass Url string as given below.
Server.MapPath("../images/image.gif")

How to designate the name of a file that a user downloads via an ASHX downloader?

This is my first time writing code that allows a user to download a file uploaded by another user.
I've written an ASHX file, download.ashx, with code that looks like this:
s = context.Request.QueryString.ToString();
byte[] buffer = new ReplacementTicketFileIO().GetSpecifiedFile(s);
context.Response.BinaryWrite(buffer);
context.Response.Flush();
context.Response.End();
When a user clicks on a link to download.ashx with the appropriate querystring, the file is downloaded, but the browser wants to display the content in the browser window. If the user right-clicks on the link, he can download the file, but the name of the file defaults to download.ashx.
I would like to accomplish two things:
1) I would like to be able to specify the default name of the file downloaded on the user's device based on the querystring.
For instance, if the user clicks on download.ashx?linkedfile=car.pdf, I would like for the browser to default to car.pdf for the name of this file.
2) I would like for the browser to default to saving the link, as opposed to opening the link in the browser window.
Is it reasonable for me to want to do this, or is there a better way to download files? Please let me know.
Set the Content-Disposition HTTP header. E.g.
Content-Disposition: attachment; filename=hello.jpg
You can do that in C# using:
Response.AddHeader("Content-Disposition", "attachment; filename=hello.jpg");
Here is something I have for excel files and I believe it forces a download rather than a new window. There is a page property for QueryString. You would just need to capture the QueryString and use it in this code as well as determining the content type. The String.Format will give you clean code.
private string _ExcelFilename
{
get
{
return (Request.QueryString["xls"] != null) ? Request.QueryString"xls"] : "bis";
}
}
Page.Response.Clear();
Page.EnableViewState = false;
Page.Response.Clear();
Page.Response.ContentType = "application/vnd.ms-excel";
Page.Response.AppendHeader("Content-Disposition", String.Format("attachment; filename={0}_{1}.xls", _ExcelFilename, DateTime.Now.ToString("yyyyMMdd")));
Page.Response.Write(excel);
Page.Response.Flush();
Page.Response.End();

Resources