0

For a week I am working on a project, which has a functionality of uploading and downloading pdf and jpg files, the project is from a friend but it was assigned to me because he went on a trip.

The point is that this functionality of uploading and downloading files is very curious and I have made several changes which has caused me severe problems in downloading files.

Initially we have a web form (ASPX) which is part of a MasterPage, in one part of this form an ASCX control is implemented, this control is the one that has all the loading and unloading of files, within this control there is a button to add a file loader (HyperLink) and another to download (button with flag runat = "server"), the final part is a GridView, the code looks like this:

<%@ Control Language="C#" CodeBehind="MultiUpload.ascx.cs" Inherits="D_Soft.DynamicData.FieldTemplates.MultiUpload" %>
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" Tagprefix="cc1" %>

<fieldset class="fUploadControl">
    <legend>
        <h1>Upload Files</h1>
    </legend>
    <asp:UpdatePanel ID="upMultiUpload" runat="server" UpdateMode="Always">
        <ContentTemplate>

            <asp:Panel ID="pnlUpload" runat="server">

                <asp:FileUpload ID="upldFile_0" CssClass="form-control" runat="server" />

            </asp:Panel>
            <br />

            <div class="row">
            <div class="col-xs-12 col-sm-12 col-md-2 col-lg-2">
                <asp:HyperLink ID="lnkAddFileUpload" CssClass="btn btn-block btn-primary" NavigateUrl="javascript:addFileUploadCtrl();" runat="server"><i class="fa fa-plus"></i>&nbsp;&nbsp;Add</asp:HyperLink>
            </div>
            <div class="col-xs-12 col-sm-12 col-md-2 col-lg-2">
                <button runat="server" id="btnUpload" data-ajax="false" type="button" onserverclick="btnUpload_Click" class="btn btn-block btn-primary"><i class="fa fa-upload"></i>&nbsp;&nbsp;Upload</button>
            </div>

        </div>
        </ContentTemplate>
        <Triggers>
            <asp:PostBackTrigger ControlID="btnUpload" />
        </Triggers>
    </asp:UpdatePanel>

    <br />

    <div class="row">
        <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
            <div style="width: 100%; overflow: auto">
                    <asp:GridView ID="GridFiles" runat="server"
                        AutoGenerateColumns="False" CellPadding="3" DataKeyNames="RowId,File,Path,Exists"
                        Font-Names="Calibri" Font-Size="10pt" OnRowDeleting="GridFilesArchivos_RowDeleting" OnSelectedIndexChanged="GridFiles_SelectedIndexChanged"
                        ForeColor="#333333" GridLines="Both" Height="25px"
                        Width="500px"
                        Style="font-size: 10pt"
                        CssClass="mGrid" PagerStyle-CssClass="pgr" AlternatingRowStyle-CssClass="alt">
                        <FooterStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" />
                        <RowStyle BackColor="#F7F6F3" ForeColor="#333333" />
                        <PagerStyle BackColor="#284775" ForeColor="White" HorizontalAlign="Center" />
                        <SelectedRowStyle BackColor="#E2DED6" Font-Bold="True" ForeColor="#333333" />
                        <HeaderStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" />
                        <Columns>
                            <asp:BoundField DataField="RowId" SortExpression="RowId" Visible="False" />
                            <asp:BoundField DataField="File" HeaderText="FILE" SortExpression="File">
                                <HeaderStyle HorizontalAlign="Center" />
                                <ItemStyle Width="85%" HorizontalAlign="Center" />
                            </asp:BoundField>
                            <asp:BoundField DataField="Path" SortExpression="Path" Visible="False" />
                            <asp:BoundField DataField="Exists" SortExpression="Exists" Visible="False" />
                            <asp:CommandField ItemStyle-Width="15%" ItemStyle-HorizontalAlign="Center" ShowCancelButton="false" HeaderText="ACTION" ButtonType="Image" Visible="true" DeleteImageUrl="~/img/trash.png" ShowDeleteButton="True" ShowSelectButton="true" SelectImageUrl="~/img/download.png" />
                        </Columns>
                    </asp:GridView>
            </div>
        </div>
    </div>
</fieldset>

And the GUI look this:

enter image description here

For the code C # has a file upload and file download event, however, I had to make changes since some web form controls are adapted to Postback calls and I do not want the page to load again, what you see something like this:

protected void Page_Load(object sender, EventArgs e)
{
    Page.Form.Attributes.Add("enctype", "multipart/form-data");
}

protected void btnUpload_Click(object sender, EventArgs e)
{
    UploadFiles();
}

public bool UploadFiles()
{
    DataTable dtFiles = new DataTable();

    dtFiles.Columns.Add(new DataColumn("RowId", typeof(int)));
    dtFiles.Columns.Add(new DataColumn("File", typeof(string)));
    dtFiles.Columns.Add(new DataColumn("Path", typeof(string)));
    dtFiles.Columns.Add(new DataColumn("Exists", typeof(string)));

    //Number of files, here the files to be uploaded are captured, 
    //before uploading any file valid the size, name and extension of the 
    //file, this code I have omitted because I do not think it is necessary

    HttpFileCollection col = Request.Files;

    int cantFiles = 0;

    //This code allows me to save each of the files in Request.Files

    for (int i = 0; i < fcol.Count; i++)
    {
        HttpPostedFile postedF = col[i];
        if (postedF.ContentLength > 0)
        {
            string tmpsave = string.Format("{0}\\{1}", dirPath, Path.GetFileName(postedF.FileName));

            //Create a temporary file name that will be used for checking duplicates

            string tempfileName = "";

            // Check if there is already a file with the same name to load

            if (System.IO.File.Exists(tmpsave))
            {
                int counter = 2;
                while (System.IO.File.Exists(tmpsave))
                {
                    tempfileName = counter.ToString() +"_"+ Path.GetFileName(postedF.FileName);
                    tmpsave= string.Format("{0}\\{1}", dirPath, tempfileName);
                    counter++;
                }
            }

            //Save File in server

            postedF.SaveAs(tmpsave);

            //Update Rows

            DataRow dwRow = dtFiles.NewRow();

            dwRow["RowId"] = cantFiles;
            dwRow["File"] = Path.GetFileName(postedF.FileName);
            dwRow["Path"] = tmpsave;
            dwRow["Exists"] = "NO";

            dtFiles.Rows.Add(dwRow);

            cantFiles++;
        }
    }

    //Update GridView

    GridFiles.DataSource = dtFiles;
    GridFiles.DataBind();
}

protected void GridArchivos_SelectedIndexChanged(object sender, EventArgs e)
{
    string stPathDes = this.GridFiles.DataKeys[this.GridFiles.SelectedIndex][2].ToString();

    DownloadFile(HttpContext.Current, stPathDes, Path.GetFileNameWithoutExtension(stPathDes) + Path.GetExtension(stPathDes).ToLower());
}

public static void DownloadFile(System.Web.HttpContext context, string stUbication, string stName)
{

    stUbication can be: "D:\\Project\\ProjectUpload\\ProjectUpload.Web\\Files\\anyfolder\\\\123.pdf"

    stName can be: "123.pdf"

    try
    {
        System.IO.FileInfo toDownload = new System.IO.FileInfo(stUbication);
        System.Web.HttpResponse response = context.Response;

        if (toDownload.Exists)
        {
            response.ClearContent();
            response.Clear();
            response.AddHeader("Content-Disposition", "attachment; filename=" + stName);
            response.AddHeader("Content-Length", toDownload.Length.ToString());
            response.ContentType = "application/octet-stream";
            response.WriteFile(stUbication);
            response.Flush();
            //response.End();
            context.ApplicationInstance.CompleteRequest();
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

The first line of the Page_Load method together with the implementation of the UpdatePanel and the PostBackTrigger allow me to load multiple files, this I did because the Request.File variable always arrived empty.

Now the file upload works without problems until now. The line response.End(); is commented because I had generated an exception of type "Unable to evaluate the expression because the code is optimized or a native frame is on top of the call stack".

The problem is that pressing the button to download the file is never downloaded and the progress bar is triggered, in addition to this an error arises in the JavaScript console ("Cannot read property 'PRM_ParserErrorDetails' of undefined"):

enter image description here

The error does not have much documentation and I really do not know if I'm building a code incorrectly or I need to implement something else.

This control is implemented in the web form (ASPX) as follows:

<%@ Page Title="" Language="C#" MasterPageFile="~/TheMaster.Master" AutoEventWireup="true" CodeBehind="MyForm.aspx.cs" Inherits="ProjectUpload.Web.MyForm" MaintainScrollPositionOnPostback="true" %>
<%@ Register Src="~/Controls/MultiUpload.ascx" TagPrefix="uc1" TagName="MultiUpload" %>

<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">

    <asp:UpdatePanel ID="upPanelRequest" runat="server">
        <ContentTemplate>

            //In this UpdatePanel I have a button (btnButtonSave)
            //I do this to not refresh the page again, this button performs a process with the database, 
            //therefore, it is delayed and I need to do the Return to show a progress bar (gif)

            <uc1:MultiUpload runat="server" id="MultiUpload" />

            <button runat="server" type="button" id="btnButtonSave" onclick="DisableButton(this);" onserverclick="btnButtonSave_ServerClick" class="btn btn-success btn-block">
                <i class="fa fa-save"></i>&nbsp;&nbsp;SAVE
            </button>

        </ContentTemplate>
        <Triggers>
            <asp:AsyncPostBackTrigger ControlID="btnButtonSave" /> 
            <asp:AsyncPostBackTrigger ControlID="MultiUpload" /> 
        </Triggers>
    </asp:UpdatePanel>

</asp:Content>

Something strange that I have noticed is that when I upload a file, the form reloads completely. What could I be using wrong?

Can anybody help me?

Julián
  • 1,238
  • 1
  • 12
  • 24

1 Answers1

0

I found a solution and it's quite simple, you just have to put the GridView in the UpdatePanel and point to a PostBackTrigger in that control:

<asp:UpdatePanel ID="upMultiUpload" runat="server" UpdateMode="Always">
    <ContentTemplate>

        <asp:GridView ID="GridFiles" runat="server"> ... </asp:GridView>

    </ContentTemplate>
    <Triggers>

        <asp:PostBackTrigger ControlID="btnUpload" />
        <asp:PostBackTrigger ControlID="GridFiles" />

    </Triggers>
</asp:UpdatePanel>

The problem with JavaScript disappears with this, but it is necessary to modify the code to disarm the file:

response.ClearContent();
response.Clear();
response.AddHeader("Content-Disposition", "attachment; filename=" + stName);
response.AddHeader("Content-Length", toDownload.Length.ToString());
response.ContentType = "application/octet-stream";
response.WriteFile(stUbication);
response.Flush();

However it does NOT work without Postback, because it is necessary to reload the page to send the files, some implementations that I found on the Internet were with the AsyncFileUpload control but it does not adapt to my project because I am in charge of multiple files, other implementations they use AJAX and ASHX but in my case I need the GridView ... I still do not know if there is a solution to this question.

These links were of great help to understand the problem:

File upload is not working with AsyncPostBackTrigger in ASP.Net

https://forums.asp.net/t/1669892.aspx?Request+Files+is+empty

Julián
  • 1,238
  • 1
  • 12
  • 24