How to upload image file in gridview? - c#

I have a gridview that shows an image as part of a column. In Edit mode, I would like to let the user upload a new image file, so I'm using the FileUpload control in the edit part of the template.
When I click on update it's showing me this:
My code:
protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
Label lb = GridView1.HeaderRow.FindControl("Label1") as Label;
GridViewRow row = GridView1.Rows[e.RowIndex];
FileUpload fu = row.Cells[0].FindControl("fileupload") as FileUpload;
if (fu.HasFile)
{
string file = System.IO.Path.Combine(Server.MapPath("~/uploadedimages/"), fu.FileName);
fu.SaveAs(file);
using (Ex_RepeaterEntities entities = new Ex_RepeaterEntities())
{
Student students = (from e1 in entities.Students
where e1.Id == Convert.ToInt32(lb.Text)
select e1).First();
students.Images = file;
entities.SaveChanges();
}
}
}

After a lot of searching I found solution of above error by using this code:
protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
int RowID = Convert.ToInt32(GridView1.DataKeys[e.RowIndex].Value);
FileUpload fileUpload = GridView1.Rows[e.RowIndex].FindControl("fileupload") as FileUpload;
if (fileUpload.HasFile)
{
fileUpload.SaveAs(Server.MapPath("~/uploadedimages/" + fileUpload.FileName));
}
}
and at page.aspx:
<asp:TemplateField HeaderText="Upload Image" SortExpression="Names">
<EditItemTemplate>
<asp:FileUpload runat="server" ID="fileupload" />
</EditItemTemplate>
<ItemTemplate>
<asp:Image ImageUrl="~/uploadedimages/1.jpg" runat="server" ID="image" />
</ItemTemplate>
</asp:TemplateField>
But a little problem here is to solve which is that file is not saving.

Finally got my own solution of above post. Here is code to be changed:
if (fileUpload.HasFile)
{
fileUpload.SaveAs(Server.MapPath("uploadedimages/" + fileUpload.FileName));
}

Related

Asp.net C#: Cannot get inner content of fileuploads because the contents are not literal

I'm developing a web application using asp.net c#. I'm trying to create fileuploads dynamically. using the following code:
FileUpload[] fileuploadsarr = new FileUpload[uploads_table.Rows.Count];
int c = 0;
foreach (DataRow row in uploads_table.Rows)
{
Label att_name = new Label();
att_name.Text = row["TYPE"].ToString();
FileUpload fileupload = new FileUpload();
fileupload.CssClass = "form-control";
fileupload.ID = "fileupload"+ row["ID"].ToString();
fileupload.Attributes.Add("runat", "server");
fileuploads.Controls.Add(att_name);
fileuploads.Controls.Add(fileupload);
fileuploadsarr[c] = fileupload;
c = c + 1;
}
Session["myfileuploadsarr"] = fileuploadsarr;
when i try to reference the postedfile for each fileupload i got the null pointer exception. When i have debugged the code I've found this exception inside the parent attribute of the file upload
Parent = {InnerText = {System.Web.HttpException (0x80004005): Cannot get inner content of fileuploads because the contents are not literal.
Note: I'm adding the fileuploads on a div
<div id="fileuploads" runat="server">
</div>
i reference filesupload through:
FileUpload[] temp = (FileUpload[])Session["myfileuploadsarr"];
foreach (FileUpload row in temp)
{
OracleCommand cmd_docs = new OracleCommand();
System.IO.Stream fs = row.PostedFile.InputStream;
System.IO.BinaryReader br = new System.IO.BinaryReader(fs);
...
}
I think you better could use a ListView. It saves you the trouble of generating dynamic controls. Note the use of DataKeyNames
<asp:ListView ID="ListView1" runat="server" DataKeyNames="ID">
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Eval("TYPE") %>'></asp:Label>
<asp:FileUpload ID="FileUpload1" runat="server" CssClass="form-control" />
<br />
</ItemTemplate>
</asp:ListView>
<asp:Button ID="Button1" runat="server" Text="Upload files" OnClick="Button1_Click" />
And then in code behind you bind data to the ListView and process the uploaded files on a button click.
protected void Button1_Click(object sender, EventArgs e)
{
//loop all items in the listview
for (int i = 0; i < ListView1.Items.Count; i++)
{
//get the id from the datakeys if needed
int ID = Convert.ToInt32(ListView1.DataKeys[i].Values[0]);
//use findcontrol to locate the fileupload and cast it back
FileUpload fu = ListView1.Items[i].FindControl("FileUpload1") as FileUpload;
//check if it exists and has a file
if (fu != null && fu.HasFile)
{
//save the file
}
}
}
The binding of the DataTable uploads_table to the ListView to make this demo complete.
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack == false)
{
//bind the datatable to the listview
ListView1.DataSource = uploads_table;
ListView1.DataBind();
}
}

Manage Edits on FileUpload Control

I have a product page. I want to add my product to my database and I want also to update my product.
I have a problem with images.
When I insert the product everithing is ok.. In my aspx page I have this code:
<span>
<asp:FileUpload ID="files" runat="server" AllowMultiple="true" />
</span>
<div runat="server" id="previewImages"></div>
and when I save my product, in code behind I have this code:
string filenm = string.Empty;
HttpFileCollection fileCollection = Request.Files;
for (int i = 0; i < fileCollection.Count; i++)
{
HttpPostedFile uploadfile = fileCollection[i];
if (uploadfile.ContentLength > 0)
{
string filename = uploadfile.FileName;
System.IO.Directory.CreateDirectory(Server.MapPath("immScarpe/" + txtStyle.Text));
file.SaveAs(Server.MapPath("immScarpe/" + txtStyle.Text + "/") + fileName);
//this is pseudo-code
INSERT INTO PRODUCT_IMM (IdProduct, Path) VALUES (Id, "immScarpe/" + txtStyle.Text + "/" + fileName)
}
}
Now, the problem is that I can EDIT the saved product. When I click the edit button for a product, I have to load all it's data and let the user modify them. Also the images.
the main question is: How can I load the saved images in asp:FileUpload control?
Another thing I would like to do is to show images previews...in insert and in edit.
An Example of what I want to do is the thing that amazon does
but, if it's possible with only one FileUpload with AllowMultiple = true
I am willing to use other technologies like javascript, jquery and Ajax if it's necessary
Show Images Preview - Insert
<script src="jquery-1.10.1.min.js" type="text/javascript"></script>
<script type="text/javascript">
function ShowpImagePreview(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#previewImage').attr('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);
}
}
</script>
<asp:Image ID="previewImage" runat="server" />
<asp:FileUpload ID="FileUpload1" runat="server" onchange="ShowpImagePreview(this);" />
Here is a very basic example as to how you can handle images after they have been send to the server. In this snippet the filename of the image is fixed, but it should be enough to give you push in the right direction.
protected void Page_Load(object sender, EventArgs e)
{
//check if the file exists and show
if (File.Exists(Server.MapPath("testImage.jpg")))
{
setImage("/testImage.jpg");
}
}
//upload a new image
protected void Button1_Click(object sender, EventArgs e)
{
if (FileUpload1.HasFile)
{
try
{
FileUpload1.SaveAs(Server.MapPath("testImage.jpg"));
setImage("/testImage.jpg");
}
catch
{
//error writing file
}
}
}
//delete the image
protected void LinkButton1_Click(object sender, EventArgs e)
{
try
{
File.Delete(Server.MapPath("testImage.jpg"));
LinkButton1.Visible = false;
Image1.Visible = false;
}
catch
{
//error deleteing file
}
}
//set the image and show the delete link
private void setImage(string image)
{
Image1.ImageUrl = "/testImage.jpg";
Image1.Visible = true;
LinkButton1.Visible = true;
}
ASPX
<asp:Image ID="Image1" runat="server" Visible="false" />
<br />
<asp:LinkButton ID="LinkButton1" runat="server" Visible="false" OnClick="LinkButton1_Click">Delete image</asp:LinkButton>
<br />
<br />
<asp:FileUpload ID="FileUpload1" runat="server" />
<br />
<asp:Button ID="Button1" runat="server" Text="Upload" OnClick="Button1_Click" />
For displaying images to GridView from disk
https://www.aspsnippets.com/Articles/Display-Images-in-GridView-Control-using-the-path-stored-in-SQL-Server-database.aspx
Now you have the images shown, you want to have some replace or delete functionality on the images. You need to convert your field on the GridView for image to Template Field. You can do this by clicking on the source view of your ASPX page and replacing your ImageField or BoundField (whichever field you used in displaying the image).
See the design of the GridView on the question:
How to display image inside gridview template field without using handler class?
The way to bind the image source is in the answers in that question.
To have a delete or replace functionality, you can include a LinkButton control inside your TemplateField below the tag that displays the image.
You can set the LinkButton's CommandName property to 'Delete' or 'Replace' then on your .vb or .cs file, find the 'RowCommand' event for your GridView.
It goes something like (pseudo code only)
Protected Sub GridView_RowCommand(ByVal sender As Object, ByVal e As System.GridViewCommandEventArgs) Handles GridView.RowCommand
If e.CommandName = 'Delete' Then
'Place your delete query for your image record on the database here..
'Place your delete file from disk code here..
End If
End Sub
More info on GridView RowCommand Event
https://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridview.rowcommand(v=vs.110).aspx

JS code on clicking button inside GridView

I have a GridView control,inside of which I am having a file upload control with a button to upload files, Each FileControl have its own upload button, I am uploading files using RowCommand Event.Now I have to show progress bar of file upload control which I have implemented like in this link's 3rd answer Link with some modification in JS
The problem I am facing is that if I click on 2nd Row's upload button of GridView,Its validating only Row's Control.
This is my Grid View
<asp:GridView ID="Grid1" runat="server" AutoGenerateColumns="false" OnRowDataBound="Grid1_RowDataBound"
OnRowCommand="Grid1_RowCommand" OnRowDeleting="Grid1_RowDeleting"
CssClass="table">
<Columns>
<asp:TemplateField HeaderText="Files" ItemStyle-HorizontalAlign="Left" HeaderStyle-CssClass="GridViewHeader">
<ItemTemplate>
<asp:FileUpload ID="File1" runat="server" Width="98%" CssClass="filestat" />
<asp:Button ID="btnuploadfiles" runat="server" CommandName="upload" Text="Upload" OnClientClick="return ProgressBar('File1')" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
and my JS code
function ProgressBar(Id) {
var fileControl = GetClientID(Id).attr("id");
if (document.getElementById(fileControl).value != "") {
$("#divUpload").fadeIn("slow");
$('#popup_box').fadeIn("slow");
document.getElementById("divUpload").style.height = document.body.clientHeight + 'px';
id = setInterval("progress()", 20);
return true;
}
else {
alert("Select a file to upload");
return false;
}
}
//This function returns me ClientID of the server control
function GetClientID(id, context) {
var el = $("#" + id, context);
if (el.length < 1)
el = $("[id$=_" + id + "]", context);
return el;
}
I also have tried setting OnClientClick from RowDataBound,but its still validating only first Row.
protected void Grid1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
var btnupd = (Button)e.Row.FindControl("btnuploadfiles");
btnupd.OnClientClick = "return ProgressBar('File1')";
}
}
Try something like the following;
$("#<%=Grid1.ClientID%> tr").click(function(){
alert("Row clicked");
});
I think using the ClientID function would be more suitable and clear for you. Getting the tr clicked, you should be able to read the cells in the actual array of tds then.
Try adding this
protected void Grid1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
var button = (Button)e.Row.FindControl("btnuploadfiles");
var fileUpload = (FileUpload)e.Row.FindControl("File1");
string className = "class_" + new Random().Next();
button.Attributes.Add("class", "rowClick");
fileUpload.Attributes.Add("class", "rowClick");
button.Attributes.Add("customClass", className);
button.Attributes.Add("customClass", className);
}
}
And for script add this:
<script>
$(document).ready(function () {
$(".rowClick").click(function () {
var customClass = this.attr("customClass");
alert("Now the current row you selected has this as a common class : " + customClass);
});
});
</script>

Deleting images from folder by gridview

I have a grid view which I populated with images from a folder. I am trying to delete the image by getting their path name but it always returns me null:
Here are my codes to populate the grid view with images:
protected void GetImage()
{
string path = HttpContext.Current.Request.PhysicalApplicationPath + #"Story/Food Fit For A King";
string[] files = System.IO.Directory.GetFiles(path, "*.jpg");
IList<ImageFileInfo> imageFileList = new List<ImageFileInfo>();
foreach (string strFileName in files)
{
// Change the Absolute path to relative path of File Name and add to the List
imageFileList.Add(new ImageFileInfo { FileName = ResolveUrl(strFileName.Replace(Server.MapPath("/"), "~/")) });
}
gvStory.DataSource = imageFileList;
gvStory.DataBind();
}
And below is my code to delete :
protected void gvStory_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
GridView gvQuestion = (GridView)sender;
int row = e.RowIndex;
// Extract Values.
// string imageName = (TextBox)gvStory.Rows[row].Cells[0].FindControl("TextBox1");// RETURNS NULL
Image img = (Image)gvStory.Rows[row].Cells[0].FindControl("Image1");
string url = img.ImageUrl;
// string fileName = Path.GetFullPath(url); // RETURNS NULL
//string fileName = Path.Combine(Server.MapPath(#"Story/Food Fit For A King"), imageName);
File.Delete(fileName);
GetImage();
}
Am I doing the correct way to the the filepath of the image? But I need the full path of the image to delete it, I tried to use Path.GetFullPath(url) , it doesn't work. Need help on this.
And heres the aspx html side:
<asp:TemplateField HeaderText="Images">
<EditItemTemplate>
<asp:TextBox ID="TextBox1" runat="server" Text='<%# Eval("FileName") %>'></asp:TextBox>
</EditItemTemplate>
<ItemTemplate>
<asp:Image ID="Image1" runat="server" ImageUrl='<%# Eval("FileName") %>' Width="240" Height="160" />
</ItemTemplate>
</asp:TemplateField>
Need help on this.
If gridview row will be in edit mode, then only you can find the control that are inside <EditItemTemplate> tag. in editmode, you will get rowindex as -1. in other mode, rowindex will be greater than -1, then you can find controls that are inside <ItemTemplate> tag. Otherwise you will get null values. So, you can try this way,
protected void gvStory_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
GridView gvQuestion = (GridView)sender;
int row = e.RowIndex;
string fileName ="";
if(row==-1)
{
string imageName = (TextBox)gvStory.Rows[row].Cells[0].FindControl("TextBox1");
fileName = Path.Combine(Server.MapPath(#"Story/Food Fit For A King"),imageName);
}
else
{
Image img = (Image)gvStory.Rows[row].Cells[0].FindControl("Image1");
string url = img.ImageUrl;
fileName = Path.GetFullPath(url);
}
File.Delete(fileName);
GetImage();
}

adding functionality to an imageButton in a gridview

Hallo there
I have an ImageButton control as part of a GridView control that is displayed as an ItemTemplate and in the same GridView I have a regular Button control to which I added some code like this.
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "addToSession")
{
//get the row index stored in the CommandArgument property
int index = Convert.ToInt32(e.CommandArgument);
//get the gridview row where the command is raised
GridViewRow selectedRow = ((GridView)e.CommandSource).Rows[index];
//values stored in the text property of the cells
string ISBN = selectedRow.Cells[0].Text;
string bookTitle = selectedRow.Cells[1].Text;
string image = selectedRow.Cells[2].Text;
Service s = new Service();
Session["ISBN"] = ISBN;
Session["bookTitle"] = bookTitle;
Session["ImageUrl"] = s.returnImageUrl(bookTitle);
if (Session["userName"] == null)
{
Response.Redirect("registerPage.aspx");
}
else
{
Response.Redirect("RateBook.aspx");
}
}
else if (e.CommandName == "ratedBooks")
{
int index = Convert.ToInt32(e.CommandArgument);
GridViewRow selectedRow = ((GridView)e.CommandSource).Rows[index];
string bookTitle = selectedRow.Cells[1].Text;
Service s = new Service();
Session["ImageUrl"] = s.returnImageUrl(bookTitle);
Response.Redirect("BookRated.aspx");
}
when I run this code I get a format exception and again I am not sure why.
I have altered the image button a bit and nested the image in a link button which seems to be more correct.
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="LinkButton1" runat="server" CommandName="ratedBooks">
<asp:Image ID="ImageButton1" ImageUrl='<%#Eval("pictureUrl") %>'
runat="server" />
</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
Advice perhaps as to what to do
regards
ImageButton.CommandName is a valid property and it should work the same as Button.CommandName.
The problem, then, is most likely in your GridView1_RowCommand procedure. Can you post the entire procedure code including the part intended to handle the ImageButton click?

Categories

Resources