Error in creating download link for files - c#

I am creating a function that displays a list of files from a specific folder and enable the users to download but i am having errors that states:
"An exception of type 'System.ArgumentNullException' occurred in System.Web.dll but was not handled in user code, {"Value cannot be null.\r\nParameter name: filename"}"
in the statement:
context.Response.WriteFile(context.Request.QueryString["files"]);
My code:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
string[] files = Directory.GetFiles(#"C:\temp");
rpt.DataSource = files;
rpt.DataBind();
}
}
protected void rpt_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
{
string file = e.Item.DataItem as string;
HyperLink hyp = e.Item.FindControl("hyp") as HyperLink;
hyp.Text = file;
hyp.NavigateUrl = string.Format("~/Handlers/FileHandler.ashx?file={0}\n" , file);
}
}
public void ProcessRequest(HttpContext context)
{
context.Response.Clear();
context.Response.Buffer = true;
context.Response.ContentType = "application/octet-stream";
context.Response.AddHeader("Content-Disposition", "attachment; filename=" + context.Request.QueryString["files"]);
context.Response.WriteFile(context.Request.QueryString["files"]);
context.Response.End();
}
}

Try Request.QueryString(files) instead

May be a typo, but your code in ItemDataBound is
hyp.NavigateUrl = string.Format("~/Handlers/FileHandler.ashx?file={0}\n" , file);
Here you are setting a querystring parameter 'file'
In your handler, ProcessRequest method you are accessing 'files' parameter
context.Response.WriteFile(context.Request.QueryString["files"]);
Try changing this to
context.Response.WriteFile(context.Request.Params["file"]);

Related

How to open a pdf file in a WebForm application by search?

When I click on the listbox which search a PDF file, it's not opening.
The code is below. Any thoughts?
protected void Button1_Click(object sender, EventArgs e)
{
ListBox1.Items.Clear();
string search = TextBox1.Text;
if (TextBox1.Text != "")
{
string[] pdffiles = Directory.GetFiles(#"\\192.168.5.10\fbar\REPORT\CLOTHO\H2\REPORT\", "*" + TextBox1.Text + "*.pdf", SearchOption.AllDirectories);
foreach (string file in pdffiles)
{
// ListBox1.Items.Add(file);
ListBox1.Items.Add(Path.GetFileName(file));
}
}
else
{
Response.Write("<script>alert('For this Wafer ID Report is Not Generated');</script>");
}
}
protected void ListBox1_SelectedIndexChanged(object sender, EventArgs e)
{
string pdffiles = ListBox1.SelectedItem.ToString();
string.Format("attachment; filename={0}", fileName));
ProcessStartInfo infoOpenPdf = new ProcessStartInfo();
infoOpenPdf.FileName = pdffiles;
infoOpenPdf.Verb = "OPEN";
// Process.Start(file);
infoOpenPdf.CreateNoWindow = true;
infoOpenPdf.WindowStyle = ProcessWindowStyle.Normal;
Process openPdf = new Process();
openPdf.StartInfo = infoOpenPdf;
openPdf.Start();
}
First, you must save the file's full name to get it later. So, you must change from:
ListBox1.Items.Add(Path.GetFileName(file));
To:
ListBox1.Items.Add(new ListItem(Path.GetFileName(file), file));
Then, you should send the file from the server to the client, like this:
protected void ListBox1_SelectedIndexChanged(object sender, EventArgs e)
{
string fileName = ListBox1.SelectedValue;
byte[] fileBytes = System.IO.File.ReadAllBytes(fileName);
System.Web.HttpContext context = System.Web.HttpContext.Current;
context.Response.Clear();
context.Response.ClearHeaders();
context.Response.ClearContent();
context.Response.AppendHeader("content-length", fileBytes.Length.ToString());
context.Response.ContentType = "application/pdf";
context.Response.AppendHeader("content-disposition", "attachment; filename=" + fileName);
context.Response.BinaryWrite(fileBytes);
context.ApplicationInstance.CompleteRequest();
}
Note: don't forget to initialize your ListBox with the property AutoPostBack setted to true.

ASHX handler throwing value cannot be null error

I wanted to display a list of files in a specific folder as hyperlinks, and when the user click on the link, it will open the respective file to prompt the user to download or view but there is a constant error saying:
{"Value cannot be null.\r\nParameter name: filename"} at the line context.Response.WriteFile(context.Request.QueryString["files"]);
I've tried lots of ways but to no avail.
ASHX file:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
var directory = new DirectoryInfo("C:\\temp\\Safety&Security");
var files = (from f in directory.GetFiles()
orderby f.LastWriteTime descending
select f).First();
//string[] files = Directory.GetFiles(#"C:\temp\Safety&Security");
//files = files.Substring(files.LastIndexOf(("\\")) + 1);
rpt.DataSource = files;
rpt.DataBind();
}
if (!Page.IsPostBack)
{
string[] files = Directory.GetFiles(#"C:\temp\marketing");
Repeater1.DataSource = files;
Repeater1.DataBind();
}
if (!Page.IsPostBack)
{
string[] files = Directory.GetFiles(#"C:\temp\IT");
Repeater2.DataSource = files;
Repeater2.DataBind();
}
}
protected void rpt_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
{
string file = e.Item.DataItem as string;
HyperLink hyp = e.Item.FindControl("hyp") as HyperLink;
hyp.Text = file;
hyp.NavigateUrl = string.Format("~/Handlers/FileHandler.ashx?file={0}", file);
FileInfo f = new FileInfo(file);
FileStream s = f.Open(FileMode.OpenOrCreate, FileAccess.Read);
}
}
public void ProcessRequest(HttpContext context)
{
//Track your id
//string id = context.Request.QueryString["id"];
context.Response.Clear();
context.Response.Buffer = true;
context.Response.ContentType = "application/octet-stream";
context.Response.AddHeader("Content-Disposition", "attachment; filename=" + context.Request.QueryString["files"]);
context.Response.WriteFile(context.Request.QueryString["files"]);
context.Response.End();
}
public bool IsReusable
{
get { return false; }
}
This is the index page codes:
<li class='has-sub'><a href='#'><span>Safety, QA & Security</span></a>
<ul>
<asp:Repeater ID="rpt" runat="server" OnItemDataBound="rpt_ItemDataBound">
<ItemTemplate>
<asp:HyperLink ID="hyp" runat="server" target="_blank" a href="/Handlers/FileHandler.ashx?id=7"/>
<%-- another method of listing all files in specific folder --%>
<%--<% foreach(var file in Directory.GetFiles("C:\\temp\\Safety&Security", "*.*", SearchOption.AllDirectories)) { %>
<li><%= file.Substring(file.LastIndexOf(("\\"))+1) %></li>
<% } %> --%>
</ItemTemplate>
</asp:Repeater>
</ul>
</li>
You've made a silly mistake!
hyp.NavigateUrl = string.Format("~/Handlers/FileHandler.ashx?file={0}", file);
context.Response.WriteFile(context.Request.QueryString["files"]);
You're setting the querystring as 'file' but reading the querystring as 'files' which doesn't exist. Try
context.Response.WriteFile(context.Request.QueryString["file"]);
EDIT:
Try this code. First add a file in your c:\temp called test.txt and put some text in there. In your aspx:
<li class='has-sub'><a href='/Handlers/FileHandler.ashx?file=c:\temp\test.txt'><span>Safety, QA & Security</span></a></li>
In your handler:
public void ProcessRequest(HttpContext context)
{
//Track your id
//string id = context.Request.QueryString["id"];
context.Response.Clear();
context.Response.Buffer = true;
context.Response.ContentType = "application/octet-stream";
context.Response.AddHeader("Content-Disposition", "attachment; filename=" + context.Request.QueryString["file"]);
context.Response.WriteFile(context.Request.QueryString["file"]);
context.Response.End();
}
public bool IsReusable
{
get { return false; }
}
Set a breakpoint in your handler and make sure your handler gets hit when you debug. This code won't work as you need it to because of the other problem I mentioned in the comments about your data binding not working but you should at least get the querystring in your handler and the text file will download.

C# and ASP.NET Session casting error

I have an ASP.NET Web Forms page with an image control bound to an animated gif. If I open it in Internet Explorer (as opposed to other browsers) and click a button on the page, which opens a file, the gif stops moving even after the file is opened and closed. It won't start up again until I refresh the browser. I'm trying to solve the problem with the following code:
protected void lnkStart_Click(object sender, EventArgs e) // Link Button Click Event
{
imgRefresher.Enabled = 1 == 1; // setting Timer Control Enabled to 1
Session["TimerEnabled"] = imgRefresher.Enabled; // storing 1 in Session
Session["FileName"] = "myFile.exe";
}
protected void imgRefresher_Tick(object sender, EventArgs e) // Timer Control Tick Event
{
if (((int)Session["TimerEnabled"]) == 1) // This line gives me an invalid cast error
{
Session["TimerEnabled"] = 0 == 1;
string fileName = Session["FileName"].ToString();
// This part I stole off the internet and will actually open the file.
System.IO.FileInfo fileInfo = new System.IO.FileInfo(fileName);
if (fileInfo.Exists)
{
Response.Clear();
Response.AddHeader("Content-Disposition", "attachment; filename=" + fileInfo.Name);
Response.AddHeader("Content-Length", fileInfo.Length.ToString());
Response.ContentType = "application/octet-stream";
Response.WriteFile(fileInfo.FullName);
Response.End();
}
}
imgRefresher.Enabled = 0 == 1;
}
The line if (((byte)Session["TimerEnabled"] ^ 1) == 0) gives me an invalid cast error. I've tried casting it into an integer, a byte, a char, a float, and a double. The goal is to toggle Session["TimerEnabled"] from 1 to 0 so the next pass turns off the Timer Control.
In your case it's better to use the type bool. (you cant cast bool to int like this (int)myBool -> invalid cast error
If you wanna us an integer you can cast like this:
int myInteger = (imgRefresher.Enabled) ? 1 : 0;
Change your Code to:
protected void lnkStart_Click(object sender, EventArgs e) // Link Button Click Event
{
imgRefresher.Enabled = true; // setting Timer Control Enabled to 1
Session["TimerEnabled"] = imgRefresher.Enabled; // storing 1 in Session
Session["FileName"] = "myFile.exe";
}
protected void imgRefresher_Tick(object sender, EventArgs e) // Timer Control Tick Event
{
if (Session["TimerEnabled"]) // This line gives me an invalid cast error
{
Session["TimerEnabled"] = false;
string fileName = Session["FileName"].ToString();
// This part I stole off the internet and will actually open the file.
System.IO.FileInfo fileInfo = new System.IO.FileInfo(fileName);
if (fileInfo.Exists)
{
Response.Clear();
Response.AddHeader("Content-Disposition", "attachment; filename=" + fileInfo.Name);
Response.AddHeader("Content-Length", fileInfo.Length.ToString());
Response.ContentType = "application/octet-stream";
Response.WriteFile(fileInfo.FullName);
Response.End();
}
}
imgRefresher.Enabled = false;
}

Download from the tree node within a folder

protected void Page_Load(object sender, EventArgs e)
{
field1.Text = (string)(Session["rolename"]); //from the page before. eg:IT Folder
field2.Text = (string)(Session["fullname"]);
if (Page.IsPostBack == false)
{
System.IO.DirectoryInfo RootDir = new System.IO.DirectoryInfo("C:\\Documents and Settings\\itdept\\Desktop\\Files\\"+ field1.Text);
TreeNode RootNode = OutputDirectory(RootDir, null);
MyTree.Nodes.Add(RootNode);
}
}
protected void click(object sender, EventArgs e) //onselectednodechanged from the treenode in aspx page
{
string file = ("C:\\Documents and Settings\\itdept\\Desktop\\Files\\" + field1.Text + "\\" + MyTree.SelectedValue);
Response.Clear();
Response.AppendHeader("Content-Disposition", "attachment;filename=" + file);
Response.ContentType = "text/xml";
Response.WriteFile(file); // here is the problem
Response.End();
}
**i can download files from the IT Folder, but in case there is a folder inside the IT Folder and i want to download something from that folder, i cannot download it.
does anyone have an idea how to make all things inside a folder even in a folder is downloadable?
thank you. :D

Dynamically added link button click event does not execute

I have dynamically added few link buttons inside a grid view with this code:
protected void gvTicketStatus_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
string compositeFiles = e.Row.Cells[3].Text;
// split the string into individual files using delemeter "?"
string[] fileSet = compositeFiles.Split('?');
e.Row.Cells[3].Text = "";
foreach (string str in fileSet)
{
if (str != null)
{
// add a link button to the cell of the data grid.
LinkButton lb = new LinkButton();
lb.Text = "Download File";
lb.ID = str; // str is file URL
lb.Click += new EventHandler(lbStatus_click);
e.Row.Cells[3].Controls.Add(lb);
}
}
}
}
In my event handler, I have read the URL from the ID and downloading the file as octet stream.
private void lbStatus_click(object sender, EventArgs e)
{
string fileName = ((Control)sender).ID;
FileInfo file = new FileInfo(fileName);
if (fileName != string.Empty && file.Exists)
{
Response.Clear();
Response.AddHeader("Content-disposition", "attachment; filename=" + fileName.Substring(fileName.LastIndexOf("\\") + 1));
Response.AddHeader("content-Length", file.Length.ToString());
Response.ContentType = "application/octet-stream";
Response.WriteFile(file.FullName);
Response.Flush();
Response.Close();
}
}
The link bottons appear in the webpage fine, but the problem is when I click on them, the page simply gets refreshed and nothing happens. The event handler code never gets executed.
Is this problem related to postback of the page? if yes then how can I solve it?
You need to suscribe to the command event of the grid view and add whatever information you need to the CommandArgs property.
EDIT: Added example
public void Page_Load(object sender, EventArgs e ){
gvTicketStatus.RowCommand += new EventHandler(RowCommand);
}
protected void gvTicketStatus_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
string compositeFiles = e.Row.Cells[3].Text;
// split the string into individual files using delemeter "?"
string[] fileSet = compositeFiles.Split('?');
e.Row.Cells[3].Text = "";
foreach (string str in fileSet)
{
if (str != null)
{
// add a link button to the cell of the data grid.
LinkButton lb = new LinkButton();
lb.Text = "Download File";
lb.CommandName = "download"; //this is useful if you need to add more links with different commands.
lb.CommandArgument = str;// str is file URL
e.Row.Cells[3].Controls.Add(lb);
}
}
}
}
In my event handler, I have read the URL from the ID and downloading the file as octet stream.
private void RowCommand(object sender, GridViewCommandEventArgs e)
{
string fileName = e.CommandArgument;
FileInfo file = new FileInfo(fileName);
if (fileName != string.Empty && file.Exists)
{
Response.Clear();
Response.AddHeader("Content-disposition", "attachment; filename=" + fileName.Substring(fileName.LastIndexOf("\\") + 1));
Response.AddHeader("content-Length", file.Length.ToString());
Response.ContentType = "application/octet-stream";
Response.WriteFile(file.FullName);
Response.Flush();
Response.Close();
}
}
For more information, please read http://msdn.microsoft.com/library/system.web.ui.webcontrols.gridview.rowcommand(v=vs.80).aspx
I've seen this behavior many times before when adding controls dynamically. Make sure that the code which binds your datagrid (which in turn executes your gvTicketStatus_RowDataBound event) runs after each and every page postback. This needs to occur in order for the linkbutton control to persist its click event after the postback.

Categories

Resources