如何在ASP .NET C#中使用GridView上载和下载多个文件而无需页面刷新?

时间:2019-01-19 16:21:19

标签: c# asp.net file-upload webforms

我从事一个项目有一个星期,该项目具有上载和下载pdf和jpg文件的功能,该项目来自一个朋友,但由于他出差而被分配给我。

关键是这种上传和下载文件的功能非常有趣,我进行了一些更改,这使我在下载文件时遇到了严重问题。

最初,我们有一个Web表单(ASPX),它是MasterPage的一部分,在该表单的一部分中,实现了ASCX控件,该控件是具有所有文件加载和卸载功能的控件。是一个用于添加文件加载器(HyperLink)的按钮,另一个是用于下载(带有标志runat =“ server”的按钮)的按钮,最后一部分是GridView,代码如下:

<%@ 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>

GUI如下所示:

enter image description here

对于代码C#,有一个文件上传和文件下载事件,但是,我必须进行更改,因为某些Web表单控件适用于回发调用,并且我不希望页面再次加载,您会看到类似这个:

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;
    }
}

Page_Load方法的第一行以及UpdatePanel和PostBackTrigger的实现允许我加载多个文件,之所以这样做是因为Request.File变量始终为空。

现在,文件上传可以正常工作了。行response.End();之所以被注释,是因为我生成了一个类型为“由于代码已优化或本机框架位于调用堆栈顶部而无法评估表达式”的异常。

问题是从不下载按钮来下载文件,而不会触发进度条,除此之外,JavaScript控制台中还会发生错误(“无法读取未定义的属性'PRM_ParserErrorDetails'”):

enter image description here

该错误没有太多的文档,我真的不知道我是在错误地构建代码还是需要实现其他东西。

此控件通过Web表单(ASPX)实现,如下所示:

<%@ 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>

我注意到的一件奇怪的事是,当我上传文件时,表单会完全重新加载。我可能用错了什么?

有人可以帮助我吗?

1 个答案:

答案 0 :(得分:0)

我找到了一个解决方案,它很简单,您只需要将GridView放在UpdatePanel中并指向该控件中的PostBackTrigger:

<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>

与此相关的JavaScript问题消失了,但是有必要修改代码以撤消文件:

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();

但是,如果没有回发,它将无法工作,因为必须重新加载页面以发送文件,所以我在Internet上发现的某些实现是通过AsyncFileUpload控件实现的,但由于我负责,因此它不适用于我的项目多个文件,其他实现使用AJAX和ASHX,但就我而言,我需要GridView ...我仍然不知道是否有解决此问题的方法。

这些链接对于理解该问题很有帮助:

File upload is not working with AsyncPostBackTrigger in ASP.Net

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