ASP.NET 多附件上傳實現代碼_實用技巧

來源:互聯網
上載者:User
但基本前提都是事先通過js指令碼來動態建立DOM,然後上傳的時候在服務端做一下處理,有點類似於163的郵件系統。檔案上傳需要通過頁面的POST方法進行提交,這個我在一次MOSS開發中iFrame表單提交的古怪問題解決一問中已經闡述過,其中包括了如何使用頁面隱藏的iFrame來提交表單從而避免整個頁面提交到伺服器而導致頁面的重新整理。多附件上傳的原理與之類似,只不過需要事先通過指令碼在頁面上動態建立多個input type='file'的標籤,當然,如果要想功能更加完美,你可能還需要通過指令碼動態添加一些按鈕事件以讓使用者可以刪除他所添加的檔案。下面是一個應用效果的截圖。

 

其中紅色方框內的內容是通過指令碼在頁面上動態建立的,將使用者在用戶端所選檔案的檔案名稱動態添加到一個div裡,同時在這個div中放一個隱藏的input type='file'的標籤,它的value為使用者所選檔案的路徑,然後在div中放置一個img,添加onmouseover和onmouseout事件為圖片增加了一些滑鼠滑動時的效果,onclick事件用來響應使用者點擊img時刪除對應的檔案。看一下代碼中的具體實現。

複製代碼 代碼如下:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script src="MultiAffix.js" type="text/javascript"></script>
<script type="text/javascript">
var controlName = 1; // This variable is for the dynamic file controls's name.

function addImg(targetElement, savestatsElement, oldimgElement) {
var browseimgElement = $get("browseimg");
var arr = browseimgElement.getElementsByTagName('input');
if (arr.length == 0 || arr[0].value.length == 0) {

alert('No file inputs.');
return;
}
var oldbrowser = arr[0];
var filename = getfilename(oldbrowser.value);
if (!validateimgtype(oldbrowser.value)) return;
if (!validateimgcount(targetElement, 3)) return;
var imgtitles = savestatsElement.value + oldimgElement.value;
if (validateimgexist(filename, imgtitles)) { alert('You have already added this image!'); return; }
if (oldbrowser != undefined) {
var newbrowser = oldbrowser.cloneNode(true);
newbrowser.value = '';
var newfile = document.createElement('div');
newfile.innerHTML = filename + '  ';

// Create a button element for delete the image.
var newfileimgbutton = document.createElement('img');
newfileimgbutton.src = 'ShoutOut_Close.gif';
newfileimgbutton.alt = 'Delete';
newfileimgbutton.onclick = function() {
this.parentNode.parentNode.removeChild(this.parentNode);
savestatsElement.value = updatehiddenimgs(filename, savestatsElement.value);
}
newfileimgbutton.onmouseover = function() {
this.src = 'ShoutOut_Close_rollover.gif';
}
newfileimgbutton.onmouseout = function() {
this.src = 'ShoutOut_Close.gif';
}

browseimgElement.replaceChild(newbrowser, oldbrowser);
oldbrowser.name = ++controlName;
oldbrowser.style.display = 'none';
newfile.appendChild(oldbrowser);

newfile.appendChild(newfileimgbutton);
targetElement.appendChild(newfile);

$get("chkAgree").checked = false;
$get("btAdd").disabled = true;
savestatsElement.value += filename + '|';
}
}
</script>

</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<div>
<div>
Description:
<asp:TextBox ID="tbDescription" MaxLength="2000" runat="server" TextMode="MultiLine"></asp:TextBox>
</div>
<div>
Location:
<asp:DropDownList ID="ddlLocation" runat="server">
</asp:DropDownList>
</div>
<div>
Display Posted By User:
<asp:CheckBox ID="chkPostedByUser" Checked="true" runat="server" />
</div>
<div>
Notify Shout out User:
<asp:CheckBox ID="chkNotifyUser" runat="server" />
</div>
<div>
Notify Shout out to Email:
<asp:TextBox ID="tbShoutoutToEmail" MaxLength="25" runat="server"></asp:TextBox>
</div>
<div>
Images:
<div id="saveshoutoutimgs" runat="server">
</div>
<input id="btAddImage" type="button" onclick="$get('saveshoutoutaddimgs').style.display='block';this.disabled=true;"
value="Click here to Add Image" />
</div>
<div id="saveshoutoutdetailshowimg">
<div id="saveshoutoutaddimgs" style="display: none;">
<div>
Add Image:</div>
<div id="browseimg">
<input type="file" />
</div>
<div>
Size limit of the images is 100kb. Hieght and Width of the images should not exceed
200px.</div>
<div>
<input id="chkAgree" type="checkbox" onclick="$get('btAdd').disabled=!this.checked;" />I
agree.legal signoff text to be defined.
</div>
<div>
<input id="btAdd" disabled="disabled" type="button" value="Add" runat="server" />
</div>
</div>
</div>
</div>
<asp:TextBox ID="tbImgs" runat="server" Text="|" Style="display: none;"></asp:TextBox>
<asp:TextBox ID="tbOldImgs" runat="server" Text="|" Style="display: none;"></asp:TextBox>
</form>
</body>
</html>

複製代碼 代碼如下:

protected void Page_Load(object sender, EventArgs e)
{
string script = string.Format("addImg($get('{0}'), $get('{1}'), $get('{2}'));",
this.saveshoutoutimgs.ClientID,
this.tbImgs.ClientID,
this.tbOldImgs.ClientID);
this.btAdd.Attributes.Add("onclick", script);
}

代碼建立在Ajax.net基礎之上,環境是Visual Studio 2008 + Windows 2003,測試通過!

簡單做一下說明:

1. <div id="saveshoutoutimg" runat="server"/>用來存放動態添加的檔案相關標籤。

2. btAddImage被點擊後自身將被disabled掉,然後顯示saveshoutoutaddimgs整個div。

3. 在saveshoutoutaddimgs中使用者可以完成檔案的選取和確認操作,chkAgree用來enable btAdd按鈕。

4. 當使用者點擊btAdd時,觸發onclick事件,該事件在code-behind的Page_Load方法中註冊,因為指令碼中涉及到使用服務端控制項的ClientID屬性,這樣寫比較方便。

5. 用戶端函數addImg用來完成動態DOM的添加操作,它接收三個參數,第一個參數targetElement表示存放動態DOM的宿主DIV,第二個參數savestatsElement表示用於儲存已添加檔案資訊的隱藏文字框,第三個參數oldimgElement表示用於儲存在編輯狀態下使用者上一次上傳的檔案資訊隱藏文字框。基本思路是複製browseimg下的input type="file"標籤,然後將動態產生的DOM添加到saveshoutoutimgs下,並同時附加了一些事件。

6. tbImgs隱藏文字框用來儲存使用者已選檔案的資訊,以"|檔案名稱1|檔案名稱2|檔案名稱3|..."的格式存放;tbOldImgs隱藏文字框中的值在編輯狀態下才會得到,其中儲存了使用者上一次所上傳檔案的資訊,儲存格式與tbImgs相同。

7. 在編輯狀態下,在服務端向saveshoutoutimgs標籤添加與addImg指令碼函數所產生的動態DOM相同的標籤,並同時往tbOldImgs隱藏文字框中寫入檔案資訊。我在這裡寫了一個樣本,讀者可以自己完善代碼用以驗證。在顯示檔案時我在檔案的名稱上添加了一個連結,這個連結所指向的頁面用於輸出圖片,如通過得到的圖片ID在資料庫中檢索圖片的位元據然後Write到頁面上。ImageEntity為自訂Image對象的實體類,用以儲存圖片檔案的相關資訊。
複製代碼 代碼如下:

public void SetImages(List<ImageEntity> images)
{
if (images.Count > 0)
{
this.tbOldImgs.Text = "|";
foreach (ImageEntity image in images)
{
HtmlGenericControl imgDiv = new HtmlGenericControl("Div");

HtmlAnchor imgAnchor = new HtmlAnchor();
imgAnchor.HRef = string.Format("Thumbnail.aspx?isthumbnail=false&basecommentid={0}&imagetitle={1}",
image.ID.ToString(), image.Title);
imgAnchor.Target = "_blank";
imgAnchor.Title = image.Title;
imgAnchor.InnerHtml = image.Title + "  ";

HtmlImage imgButton = new HtmlImage();
imgButton.Src = "ShoutOut_Close.gif";
imgButton.Alt = "Delete";
imgButton.Attributes["onclick"] = string.Format("this.parentNode.parentNode.removeChild(this.parentNode);$get('{0}').value = updatehiddenimgs('{1}',$get('{0}').value);",
this.tbOldImgs.ClientID, image.Title);
imgButton.Attributes["onmouseover"] = "this.src='ShoutOut_Close_rollover.gif'";
imgButton.Attributes["onmouseout"] = "this.src='ShoutOut_Close.gif'";

imgDiv.Controls.Add(imgAnchor);
imgDiv.Controls.Add(imgButton);
this.saveshoutoutimgs.Controls.Add(imgDiv);
this.tbOldImgs.Text += image.Title + "|";
}
}
}



public class ImageEntity
{
public ImageEntity()
{
}

public ImageEntity(int id, string title, Byte[] imageBlob, string type)
{
ID = id;
Title = title;
ImageBlob = imageBlob;
Type = type;
}

public int ID { get; set; }
public string Title { get; set; }
public string Type { get; set; }
public Byte[] ImageBlob { get; set; }
}

有一個問題需要注意,當儲存編輯狀態下的資料時,在服務端需要重新刪除原有圖片然後再重新添加圖片,對於使用者未在用戶端修改的圖片,則需要在儲存資料前通過tbOldImgs隱藏欄位中的相關資訊重新檢索得到圖片資料,然後重新儲存圖片。例如編輯狀態下得到A、B、C三張圖片,使用者刪除了圖片C,添加了圖片D,則儲存時在服務端這樣操作:先通過tbOldImgs隱藏欄位得到剩餘的舊圖片資訊(即圖片A和圖片B),從資料庫中檢索出這些圖片的資料,儲存前先刪除與該條資料相關的所有已上傳圖片,然後與得到的新圖片(即圖片D)一併存入資料庫中。

還有一點就是,如果想要實現上傳圖片前判斷圖片檔案的大小,必須通過C#代碼來實現,這個不能簡單地通過js指令碼來實現,因為涉及到瀏覽器對用戶端檔案存取權限的限制。也就是說,需要將頁面預先提交到伺服器,判斷完成後通知用戶端接下來的行為,為了避免頁面提交時用戶端原有的狀態丟失,可以採用隱藏iFrame的方式提交頁面,這個在文章的一開始我已經提到過了。

總之,在Web中實現多附件上傳必須藉助於javascript來動態建立DOM,編輯狀態下可以在服務端將事先處理好的DOM添加到頁面上,並同時附件指令碼事件,在服務端代碼和用戶端代碼之間注意儲存各個控制項的狀態。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.