简体   繁体   English

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

[英]How to upload and download multiple files without Page Refresh using a GridView in ASP .NET C#?

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. 我正在一个项目上工作一个星期,该项目具有上载和下载pdf和jpg文件的功能,该项目来自一个朋友,但由于他出差而被分配给我。

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: 最初,我们有一个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>

And the GUI look this: GUI如下所示:

在此处输入图片说明

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: 对于代码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;
    }
}

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. Page_Load方法的第一行以及UpdatePanel和PostBackTrigger的实现允许我加载多个文件,这是因为Request.File变量始终为空。

Now the file upload works without problems until now. 现在,文件上传可以正常工作了。 The line response.End(); 行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"): 问题在于,从不下载用于下载文件的按钮,并且不会触发进度条,此外,JavaScript控制台中还会发生错误(“无法读取未定义的属性'PRM_ParserErrorDetails'”):

在此处输入图片说明

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: 此控件以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>

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? 有谁能够帮助我?

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: 我找到了一个解决方案,它非常简单,只需要将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>

The problem with JavaScript disappears with this, but it is necessary to modify the code to disarm the file: 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();

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

These links were of great help to understand the problem: 这些链接对于了解该问题很有帮助:

File upload is not working with AsyncPostBackTrigger in ASP.Net 文件上传不适用于ASP.Net中的AsyncPostBackTrigger

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM