Как загрузить и загрузить несколько файлов без обновления страницы, используя GridView в ASP .NET C #? - PullRequest
0 голосов
/ 19 января 2019

В течение недели я работаю над проектом, который имеет функцию загрузки и скачивания файлов pdf и jpg, проект от друга, но он был назначен мне, потому что он отправился в путешествие.

Дело в том, что эта функция загрузки и выгрузки файлов очень любопытна, и я сделал несколько изменений, которые вызвали у меня серьезные проблемы с загрузкой файлов.

Изначально у нас есть веб-форма (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>

И графический интерфейс выглядит так:

enter image description here

Для кода C # есть событие загрузки файла и загрузки файла, однако мне пришлось внести изменения, поскольку некоторые элементы управления веб-формы адаптированы для вызовов Postback, и я не хочу, чтобы страница загружалась снова, как вы видите, что-то вроде это:

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 из undefined»):

enter image description here

Ошибка не имеет много документации, и я действительно не знаю, неправильно ли я строю код или мне нужно реализовать что-то еще.

Этот элемент управления реализован в веб-форме (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 голосов
/ 21 января 2019

Я нашел решение, и оно довольно простое, вам просто нужно поместить 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();

Однако, это НЕ работает без Postback, потому что необходимо перезагрузить страницу для отправки файлов, некоторые реализации, которые я нашел в Интернете, были с элементом управления AsyncFileUpload, но он не адаптируется к моему проекту, потому что я отвечаю из нескольких файлов, в других реализациях они используют AJAX и ASHX, но в моем случае мне нужен GridView ... Я до сих пор не знаю, есть ли решение этого вопроса.

Эти ссылки очень помогли понять проблему:

Загрузка файла не работает с AsyncPostBackTrigger в ASP.Net

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...