В течение недели я работаю над проектом, который имеет функцию загрузки и скачивания файлов 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> 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> 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>
И графический интерфейс выглядит так:
Для кода 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»):
Ошибка не имеет много документации, и я действительно не знаю, неправильно ли я строю код или мне нужно реализовать что-то еще.
Этот элемент управления реализован в веб-форме (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> SAVE
</button>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnButtonSave" />
<asp:AsyncPostBackTrigger ControlID="MultiUpload" />
</Triggers>
</asp:UpdatePanel>
</asp:Content>
Что-то странное, что я заметил, это то, что при загрузке файла форма полностью перезагружается. Что я могу использовать неправильно?
Кто-нибудь может мне помочь?