一种方法,也许是最简单的解决方案,就是使用<asp:FileUpload> 控件,并将其隐藏起来。再说一次,虽然如果您希望用户选择他们正在上传的文件,这很有效,但如果您想实现某种 HTML5 拖放解决方案等,它可能不是最佳解决方案。
巧合的是,上周我几乎全部都在研究如何通过 javascript 将文件上传到 ASP.NET Web 表单。我开发了一个使用 HTML5 的拖放界面,还开发了一种故障转移方法,用户可以使用该方法通过<asp:FileUpload> 控件选择和上传他们的文件。
由于该功能的优先级较低,我们仅完全开发了<asp:FileUpload> 控件,但我很高兴在这里与您分享该功能:
HTML
我们将创建一个 ASP 文件上传控件,并隐藏其中的某些部分。剩下的部分,我们可以添加样式(或者在 javascript 和 CSS 中做任何事情),让它看起来很花哨和定制。继续按钮
<!-- Allow user to upload the file via the fallbackuploader -->
<div id="fallbackUploader" class="uploader-item-fallbackuploader uploader-item fallbackuploader step-container">
<div class="fallbackuploader-item-uploadcontrols fallbackuploader-item uploadcontrols">
<!-- Uploader Label (note: this serves as the visible "choose files" button too) -->
<label id="uploader_choose_files_button" class="uploadcontrols-item uploadcontrols-item-label button animated" for="mainContent_subContent_fbu_fileuploader">
Choose Files
</label>
<!-- Choose Files button (**NOTE: you'll want to make this control invisible. Try not to set the display to none, as that may cause ASP to omit rendering it -->
<asp:FileUpload ID="fbu_fileuploader" CssClass="uploadcontrols-item-aspfileloader uploadcontrols-item aspfileloader" runat="server" />
<!-- Continue button (NOTE: this button triggers the event that on the server side that will actually handle the file upload -->
<asp:Button ID="fbu_fileuploaderButton" runat="server" Text="Continue" ClientIDMode="Static"
CssClass="uploadcontrols-item-button-upload uploadcontrols-item-button uploadcontrols-item button-upload button continue-button hidden disabled animated" />
<!-- Cancel button -->
<div id="chooseFilesCancelButton" class="uploadcontrols-item-uploadcontrols-item-button
uploadcontrols-item cancel-button hidden disabled button animated">
Go Back
</div>
</div>
</div>
Javascript
// Organizational container for the file uploader controls.
var aspUploadControlsContainer = $('.fallbackuploader-item-uploadcontrols');
// ASP control that chooses and loads the file.
var aspFileLoader_ele = aspUploadControlsContainer.children('.uploadcontrols-item-aspfileloader'),
// element that represents the "choose files" button.
aspUploaderChooseFilesLabel = aspUploadControlsContainer.find('.uploadcontrols-item-label'),
// ASP button that loads the file
aspFileLoaderButton_ele = aspUploadControlsContainer.children('.uploadcontrols-item-button'),
// the element created by the actual ASP "<asp:FileUpload>" control tag.
aspFileUploadControl_ele = aspUploadControlsContainer.find('input.uploadcontrols-item-aspfileloader'),
// the message/alert container
messagebox_ele = $('.uploader-item-messagebox');
// ------------------------------------------------------------
// Bind the 'click' and 'change' events to the file uploader
// ------------------------------------------------------------
function bindAspUploadControlEvents() {
aspFileLoader_ele.on('change', function () { // add the on-change event for the file uploader.
console.log('File changed ...');
if (!aspUploaderChooseFilesLabel.hasClass('upload-disabled')) {
console.log('Choose-files label not disabled ...');
fileSelected(); // perform the file-selected actions.
}
});
};
// ------------------------------------------------------------
// Validate the selected file name and adjust the uploader.
// ------------------------------------------------------------
function fileSelected() {
console.log('File selected...');
var f = aspFileLoader_ele.val() || '';
f = f.replace('C:\\fakepath\\', '') || ''; // get the file name <-- ASP.NET masks the path as C:\\fakepath\\ for security purposes...we'll just take that part out.
var xlRegex = /.(xlsx|xls)$/i; // set the regex to test for accepted file extensions.
if (f.length && !(f.match(xlRegex))) {
// --------------------------- FAILED - show a message -----------------------------------------------------------------
console.log('File-name invalid. Displaying error message ...');
convertCFlabelToButton(); // <-- converting the label to a button and visa versa is probably a round-about way of doing what we wanted, but we were doing some other stuff with it that kind of made it a necessary evil :)
deactivateChooseFilesCancelButton(); // if nothing selected, disable and hide cancel button <-- these functions just do some fluffy stuff that you probably won't need.
deactivateUploaderContinueButton(function () { // if nothing selected, disable and hide continue button <-- these functions just do some fluffy stuff that you probably won't need.
messagebox_ele.text("You've selected a file with an invalid file name. Please make sure the file extension ends with \".xlsx\".").show(); // show the error message.
});
} else if (f.length && f.match(xlRegex)) {
// --------------------------- PASSED -----------------------------------------------------------------
console.log('File-name validated. Hiding messages...');
messagebox_ele.text('').hide(); // reset and hide any messages
console.log('Messages hidden.');
convertCFbuttonToLabel(f, function () { // this converts the button to a label with the given file name as its text
activateUploaderContinueButton(function () { // show and enable the choose-files continue-button
activateChooseFilesCancelButton() // show and enable the choose-files cancel-button
});
});
} else {
// --------------------------- FAILED - hide message -----------------------------------------------------------------
console.log('No file detected. Returning to default state ...');
messagebox_ele.text('').hide(); // hide any messages
// reset the label to defaults
convertCFlabelToButton();
// ------------------------------------------------------------------------------------------------------------------------------
};
}
代码隐藏
现在我们只需要添加 VB.NET(或 C#)来处理继续按钮的点击事件。
Protected Sub fbu_fileuploaderButton_Click(sender As Object, e As EventArgs) Handles fbu_fileuploaderButton.Click
If fbu_fileuploader.HasFile Then
Dim FileName As String = Path.GetFileName(Path.GetRandomFileName())
Dim Extension As String = Path.GetExtension(fbu_fileuploader.PostedFile.FileName)
Dim FolderPath As String = ResolveUrl("~/" & ConfigurationManager.AppSettings("FolderPath"))
Dim FilePath As String = Server.MapPath(FolderPath + FileName)
fbu_fileuploader.SaveAs(FilePath)
GetExcelSheets(FilePath, fbu_fileuploader.PostedFile.FileName, FileName, Extension, "Yes")
End If
End Sub
其他注意事项
我们在上面的代码中做了一些我没有解释的事情,比如“FolderPath”应用程序设置(我们在 CODE-BEHIND 部分使用它来确定文件应该保存在哪里)。如果您从未在 web.config 中使用过应用程序设置,那非常简单。为了上面的例子,我们将在 <configuration> 标签之间添加以下 sn-p:
<appSettings>
<add key="FolderPath" value="uploads/"/>
</appSettings>
然后我可以使用
访问此 appSetting 的值
ResolveUrl("~/" & ConfigurationManager.AppSettings("FolderPath"))
或
ResolveUrl(String.Format("~/{0}", ConfigurationManager.AppSettings("FolderPath")))
另外,我停止使用“getExcelSheets”函数,因为它更特定于我的应用程序,可能超出了本教程的范围。
其他资源
我有一个有条不紊地保存有用书签的好习惯。这是我的“文件上传器”部分的内容...