2012-08-17 29 views
1

好吧,我有一個來自用戶的請求,我想用Event Receiver來實現。更改正在上傳的文檔的標題 - 事件接收器

基本上她想要的是擁有一個用戶可以上傳文檔的文檔庫。每個文檔都有一個文件名,如「UserA - Customization.docx」。現在您可以想象,用戶可以上傳許多具有相同名稱的文檔,因此我們想要自動爲文件編號。因此,如果用戶A上傳第一個文檔,SharePoint會在名稱後面添加一個數字,以便將文件命名爲「UserA - Customization - 1.docx」,然後他上傳第二個文檔,它將被稱爲「UserA - Customization - 2 .DOCX」。

但是,現在如果UserB想要上傳他的第一個文檔,它必須編號爲「UserB - Customization - 1.docx」,所以基本上計數器需要重新啓動,如果它的新文檔繼續從最高編號已經存在。

所以基本上,SharePoint需要檢查當前文檔的名稱是否存在於列表中,並且它是否在其旁邊添加了一個數字,但數字必須大於最高文檔1,因此它只會增加。

有沒有辦法做到這一點?有任何想法嗎?

這是我想出了迄今簡單地改變文件中添加「-XX」爲文件名的名字,但是這是行不通的。

public override void ItemAdded(SPItemEventProperties properties) 
{ 
    SPFile spf = properties.ListItem.File; 
    string url = properties.AfterUrl; 

    int positionOfSlash = url.LastIndexOf("/"); 
    string pathBeforeFileName = url.Substring(0, positionOfSlash); 
    string newFileName = createNewFileName(url.Substring(positionOfSlash)); 

    string myNewUrl = pathBeforeFileName + newFileName; 

    DisableEventFiring(); 
    spf.MoveTo(myNewUrl); 

    spf.Update(); 
    EnableEventFiring(); 
} 
static string createNewFileName(string oldFileName) 
{ 
    int positionOfPeriod = oldFileName.LastIndexOf("."); 

    string fileName = oldFileName.Substring(0, positionOfPeriod); 
    string fileExtension = oldFileName.Substring(positionOfPeriod); 

    string newFileName = fileName + "-xx" + fileExtension; 

    return newFileName; 
} 

我在哪裏出錯了這段代碼?謝謝你的幫助!

編輯:這是我正在使用Visual Studio中的控制檯應用程序來連接EventReceiver到文檔庫中的代碼。

using (SPSite site = new SPSite("http://servername:port/subsite1/subsite2/")) 
     { 

      using (SPWeb web = site.OpenWeb()) 
      { 
       SPList list = web.Lists["My Doc Library"]; 

       SPEventReceiverDefinition def = list.EventReceivers.Add(); 
       def.Assembly = "DocumentLibrary_ClassLib, Version=1.0.0.0, Culture=Neutral, PublicKeyToken=611205b34d18f14d"; 
       def.Class = "DocumentLibrary_ClassLib.EventReceiver"; 
       def.Type = SPEventReceiverType.ItemAdded; 
       def.Update(); 
      } 
     } 

編輯#2: 確定如何對這樣的事情?

//this will get just the name of the file without the extension and I will send that to the 
//query builder which will count how many files there are with that name and return 
int positionOfPeriod = oldFileName.LastIndexOf("."); 
string tempFileName = oldFileName.Substring(0, positionOfPeriod); 

SPQuery query = BuildArbitraryQuery(properties.List, "Name", tempFileName, true); 

但現在我真的不明白在BuildArbitraryQuery查詢,我怎樣才能改變這個給我所期望的行爲? (對不起,如果其總noob問題,但我從來沒有處理C#和EventReceivers之前)
- 在BuildArbitraryQuery找了一會兒,我認爲我做了一些感覺好了後,我基本上不需要改變什麼?既然它收到文件的名稱和列的名稱作爲參數,它應該沒事吧?

此外,由於列表中的項目將類似於ClientA Request - 3.docx,我將發送文件名到BuildArbitraryQuery將能夠找到部分匹配而不是完全匹配。例如,如果文件名BuildArbitraryQuery收到的是ClientA Request.docx,它是否能夠找到來自該ClientA的所有其他請求? ClientA Request - 1.docx,ClientA Request - 2.docx都將包含在計算中嗎?

回答

2

在這裏,你去,測試它,它的工作原理。

/// <summary> 
    /// An item was added. 
    /// </summary> 
    public override void ItemAdded(SPItemEventProperties properties) 
    { 
     base.ItemAdded(properties); 
     SPListItem item = properties.ListItem; 

     if (item["Name"] == null) 
      return; //or better yet, log 

     string oldFileName = item["Name"].ToString(); 

     SPQuery query = BuildArbitraryQuery(properties.List, "Created By", properties.UserDisplayName, true); 

     int count = properties.List.GetItems(query).Count; 

     int positionOfPeriod = oldFileName.LastIndexOf("."); 
     if (positionOfPeriod == -1) 
     { 
      fileName = oldFileName; 
      fileExtension = ""; 
     } 
     else 
     { 
      fileName = oldFileName.Substring(0, positionOfPeriod); 
      fileExtension = oldFileName.Substring(positionOfPeriod); 
     } 

     string newFileName = fileName + "-xx" + count.ToString() + fileExtension; 

     item["Name"] = newFileName; 

     try 
     { 
      properties.Web.AllowUnsafeUpdates = true; 
      EventFiringEnabled = false; 

      item.Update(); 
     } 
     finally 
     { 
      properties.Web.AllowUnsafeUpdates = false; 
      EventFiringEnabled = true; 
     } 
    } 

    /// <summary> 
    /// Builds an arbitrary SPQuery which filters by a single column value. 
    /// </summary> 
    /// <param name="list">The list you will run the query against.</param> 
    /// <param name="columnDisplayName">The Display Name of the column you want to filter.</param> 
    /// <param name="value">The value to filter against.</param> 
    /// <returns>A new SPQuery object ready to run against the list.</returns> 
    public static SPQuery BuildArbitraryQuery(SPList list, string columnDisplayName, string value, bool deepSearch) 
    { 
     if (list == null) 
      throw new ArgumentNullException("You cannot pass a null list to Helper.BuildArbitraryQuery."); 

     if (!list.Fields.ContainsField(columnDisplayName)) 
      throw new ArgumentException("The SharePoint List \"" + list.Title + "\" does not contain the Field \"" + columnDisplayName + "\"."); 

     string internalName = list.Fields[columnDisplayName].InternalName; 
     SPQuery query = new SPQuery(); 
     query.Query = "<Where><Eq><FieldRef Name=\"" + internalName + "\"/><Value Type=\"Text\">" + value + "</Value></Eq></Where>"; 

     if (deepSearch) 
      query.ViewAttributes += "Scope='RecursiveAll'"; 

     return query; 
    } 
+0

謝謝!但我似乎無法讓我的文檔庫工作。這是如何工作的,我嘗試創建一個具有相同名稱的新文檔,它只是覆蓋舊文檔。而且我也嘗試上傳一個與列表中的名稱相同的文檔,但它也只是覆蓋它,而且文件名不會改變。任何想法我做錯了什麼?我添加了我在控制檯項目中使用的代碼,將此事件接收器添加到文檔庫中,以添加到原始文章中。 – 2012-08-17 17:14:30

+0

當您使用與列表中已有的名稱相同的名稱上載文檔時,SharePoint不會將其計爲添加新項目。相反,sharepoint會將其作爲最初擁有該名稱的項目的更新進行計數。 我只是給了你應該在每個*新*項目上運行,因爲它被添加到庫中,並在號碼添加到文件名中的代碼。通過查看文件名,而不是試圖確定用戶上傳文檔的多少實例,它只是檢查SharePoint中記錄哪個用戶上載文件的列。 此信息有幫助嗎? – 2012-08-17 17:51:36

+0

好的,我嘗試使用功能區上的「新文檔」選項創建新文檔。我在文檔中添加了一些文本,然後點擊「保存」,然後它詢問了一個名稱,所以我輸入了與列表中已有文檔相同的名稱,但是它提供了合併,覆蓋或重命名文檔的選項。我需要在這裏爲事件接收器工作做什麼? – 2012-08-17 17:54:18