汤尼

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

  众所周知,在MOSS 2007 中,当我们为List中的某一个Item上传附件的时候,这个附件是以二进制的形式存放在数据库中的,当我们需要下载的时候,SharePoint Service再为我们还原成原来的附件。SharePoint 还为附件的大小做了限制,一般都在50M。那么如果有的用户想把一些大Size 的文件作为附件上传的时候,就会产生问题。而且大文件上传,下载均设计到数据库操作,对系统的性能要求会比较大。我们在曾经遇到过美国的同事上传附件到在中国的SharePoint server上,由于附件比较大,带宽有限,就产生过上传出错的问题。还有在MOSS2007中,附件没办法批量上传和下载到List的某个Item中,用户只要one by one的去下载附件,用户体验不够友好。

  综上需求,开发了一个自定义字段:FTP上传字段。功能如下:

  1.当用户在一个List下新建一个Item的时候,在用户设定的FTP server上自动创建一个文件夹。

  2.文件夹地址作为自定义字段的值显示,用户可以点击这个链接地址,进行批量的附件上传下载。

下面介绍详细的开发过程:

  1.首先还是创建一个自定义字段的Project

  2.先添加一个FTP的操作的工具类,我们称为FTPClientUtility,完成一切在FTP server上的操作,如附件上传,创建文件夹,计算文件夹当前大小等等

FTPClientUtility的主要方法如下:

 

代码
  public bool UploadFile(string path, string fileName, string location)
        {
            StreamReader sourceStream 
= null;
            Stream requestStream 
= null;
            FtpWebResponse response 
= null;

            
try
            {
                FtpWebRequest request 
= (FtpWebRequest)WebRequest.Create(this.FTPUrl + "/" + location + "/" + fileName);
                request.Method 
= WebRequestMethods.Ftp.UploadFile;
                request.UseBinary 
= true;
                request.Credentials 
= new NetworkCredential(this.UserName, this.Password);
                
                sourceStream 
= new StreamReader(path);
                
byte[] fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
                sourceStream.Close();
                request.ContentLength 
= fileContents.Length;

                requestStream 
= request.GetRequestStream();
                requestStream.Write(fileContents, 
0, fileContents.Length);
                requestStream.Close();

                response 
= (FtpWebResponse)request.GetResponse();
               
// string result = response.StatusDescription;
                response.Close();
                
return true;
            }
            
catch (Exception ex)
            {
                
return false;
            }
            
finally
            {
                
if (null != sourceStream)
                {
                    sourceStream.Close();
                }
                
if (null != requestStream)
                {
                    requestStream.Close();
                }
                
if (null != response)
                {
                    response.Close();
                }
            }

        }

        
public bool CreateFolder(string folderName)
        {
            FtpWebResponse response 
= null;
            
try
            {
                FtpWebRequest request 
= (FtpWebRequest)WebRequest.Create(this.FTPUrl + "/" + folderName);
                request.Method 
= WebRequestMethods.Ftp.MakeDirectory;
                request.UseBinary 
= true;
                request.Credentials 
= new NetworkCredential(this.UserName, this.Password);
                response 
= (FtpWebResponse)request.GetResponse();
                response.Close();
                
return true;
            }
            
catch (Exception ex)
            {
                
return false;
            }
            
finally
            {
                
if (null != response)
                {
                    response.Close();
                }
            }
        }

        
public bool IsFolderOrFileExist(string folderName, string destinationFolderLocation)
        {
            FtpWebResponse response 
= null;
            StreamReader reader 
= null;
            IList
<string> fileList = new List<string>();
            
try
            {
                FtpWebRequest request 
= (FtpWebRequest)WebRequest.Create(this.FTPUrl + destinationFolderLocation);
                request.Method 
= WebRequestMethods.Ftp.ListDirectory;
                request.UseBinary 
= true;
                request.Credentials 
= new NetworkCredential(this.UserName, this.Password);
                response 
= (FtpWebResponse)request.GetResponse();
                reader 
= new StreamReader(response.GetResponseStream(), Encoding.UTF8);
                
string line = String.Empty;
                
while(!String.IsNullOrEmpty(line = reader.ReadLine()))
                {
                    line 
= line.Split('_')[0];
                    fileList.Add(line);
                }
                response.Close();
                reader.Close();
                
string folderId = folderName.Split('_')[0];
                
return fileList.Contains(folderId); 
            }
            
catch (Exception ex)
            {
                
return false;
            }
            
finally
            {
                
if (null != response)
                {
                    response.Close();
                }
                
if (null != reader)
                {
                    reader.Close();
                }
            }
        }
        
public List<string> GetListDirectoryDetails(string destinationFolderLocation)
        {
            StreamReader reader 
= null;
            FtpWebResponse response 
= null;
            List
<string> fileList = new List<string>();
            
try
            {
                FtpWebRequest request 
= (FtpWebRequest)WebRequest.Create(this.FTPUrl + destinationFolderLocation);
                request.Method 
= WebRequestMethods.Ftp.ListDirectoryDetails;
                request.UseBinary 
= true;
                request.Credentials 
= new NetworkCredential(this.UserName, this.Password);
                response 
= (FtpWebResponse)request.GetResponse();
                reader 
= new StreamReader(response.GetResponseStream());
                
string line = "";
                
string fileName = "";
                
string folderName = "";
                
string[] info = null;
                IList
<string> filesInfo = new List<string>();
                
while (!String.IsNullOrEmpty(line = reader.ReadLine())) //Save the response stream in memory so the response can be closed and will not hanged in 
                {
                    filesInfo.Add(line);
                }
                
int startIndex = 0;
                System.Text.RegularExpressions.Regex rg 
= new System.Text.RegularExpressions.Regex(@"\d");
                
foreach (string fileLine in filesInfo)
                {
                    
if (fileLine.IndexOf("<DIR>"== -1)
                    {
                        fileName 
= rg.Replace(fileLine.Substring(20), "").Trim();
                        fileList.Add(fileName);
                    }
                    
else
                    {
                        startIndex 
= fileLine.IndexOf("<DIR>");
                        folderName 
= fileLine.Substring(startIndex + 5, fileLine.Length - startIndex - 5).Trim();
                        fileList.Add(folderName);
                    }
                }
                response.Close();
                
return fileList;
            }
            
catch (Exception ex)
            {
                
return null;
            }

        }

        
public long GetFolderSize(string destinationFolderLocation)
        {
            
long fileSize = 0;
            StreamReader reader 
= null;
            FtpWebResponse response 
= null;
            
long totalFileSize = 0;
            
try
            {
                FtpWebRequest request 
= (FtpWebRequest)WebRequest.Create(this.FTPUrl + destinationFolderLocation);
                request.Method 
= WebRequestMethods.Ftp.ListDirectoryDetails;
                request.UseBinary 
= true;
                request.Credentials 
= new NetworkCredential(this.UserName,this.Password);
                response 
= (FtpWebResponse)request.GetResponse();
                reader 
= new StreamReader(response.GetResponseStream());
                
string line = "";
                
string fileName = "";
                
string folderName = "";
                
string[] info = null;
                IList
<string> filesInfo = new List<string>();
                
while (!String.IsNullOrEmpty(line = reader.ReadLine())) //Save the response stream in memory so the response can be closed and will not hanged in 
                {
                    filesInfo.Add(line);
                }
                
int startIndex = 0;
                
foreach (string fileLine in filesInfo)
                {
                    
if (fileLine.IndexOf("<DIR>"== -1)
                    {
                        info 
= fileLine.Split(' ');
                        fileName 
= info[info.Length - 1];
                        totalFileSize 
+= Convert.ToInt64(info[info.Length - 2]);
                    }
                    
else
                    {
                        startIndex 
= fileLine.IndexOf("<DIR>");
                        folderName 
= fileLine.Substring(startIndex + 5, fileLine.Length - startIndex - 5).Trim();
                        response.Close();
                        totalFileSize 
+= GetFolderSize(destinationFolderLocation + "/" + folderName);
                    }

                }
                
return totalFileSize;
            }
            
catch (Exception ex)
            {
                
return 0;
            }
        }

        
public long GetFileSize(string fileName, string destinationFolderLocation)
        {
            
long fileSize = 0;
            FtpWebResponse response 
= null;
            
try
            {
                FileInfo fileInf 
= new FileInfo(fileName);
                FtpWebRequest request 
= (FtpWebRequest)WebRequest.Create(this.FTPUrl + destinationFolderLocation + "/" + fileInf.Name);
                request.Method 
= WebRequestMethods.Ftp.GetFileSize;
                request.UseBinary 
= true;
                request.Credentials 
= new NetworkCredential(this.UserName, this.Password);
                response 
= (FtpWebResponse)request.GetResponse();
                fileSize 
= response.ContentLength;
                response.Close();
                
return fileSize;
            }
            
catch (Exception ex)
            {
                
return 0;
            }
            
finally
            {
                
if (null != response)
                {
                    response.Close();
                } 
            }
        }

 

  3. 自定义字段的实现类,和普通的自定义字段实现类类似,没什么特别的,代码如下

 

代码
  public class FileUploadField : SPFieldText
    {
       

        
public FileUploadField(SPFieldCollection fields, string fieldName)
            : 
base(fields, fieldName)
        {
            InitProperties();
        }

        
public FileUploadField(SPFieldCollection fields, string typeName, string displayName)
            : 
base(fields, typeName, displayName)
        {
            InitProperties();
        }

        
public override BaseFieldControl FieldRenderingControl
        {
            
get
            {
                BaseFieldControl fieldControl 
= new FileUploadFieldControl(this);

                fieldControl.FieldName 
= InternalName;

                
return fieldControl;
            }
        }

   }

 

  4. 自定义字段的呈现类,当Item新建时,要完成在FTP上创建相应的文件夹的工作,当用户Edit/View时,将创建的文件夹地址作为此字段的值显示,主要代码:

 

代码
 public class FileUploadFieldControl : BaseFieldControl
    {
        
private FileUploadField field;
        
private LinkButton updateLink;
        
private HyperLink fileLink;
        
private FTPClientUtility ftpUtility;
        
private HtmlTable fileTable;
        
long folderMaxSize;
        
public FileUploadFieldControl(FileUploadField parentField)
        {
            
this.field = parentField;
            
this.updateLink = new LinkButton();
            
this.fileLink = new HyperLink();
            
this.ftpUtility = new FTPClientUtility();
            
this.fileTable = new HtmlTable();
            Dictionary
<stringstring> ftpInfo = GetFtpUrl();
            ftpUtility.FTPUrl 
= ftpInfo["Url"];
            ftpUtility.UserName 
= ftpInfo["UserName"];
            ftpUtility.Password 
= ftpInfo["Password"];
            folderMaxSize 
= Convert.ToInt64(ftpInfo["FolderSize"]);
        }

        
private Dictionary<string,string> GetFtpUrl()
        {
            
string ftpFile = Environment.CurrentDirectory + "\\FtpInfo.xml";
            Dictionary
<string,string> ftpInfo = new Dictionary<string,string>();
            XmlDocument xmlDoc 
= new XmlDocument();
            xmlDoc.Load(ftpFile);
            
string ftpUrl = xmlDoc.DocumentElement.SelectSingleNode("//Url").InnerText;
            ftpInfo.Add(
"Url", ftpUrl);
            
string userName = xmlDoc.DocumentElement.SelectSingleNode("//UserName").InnerText;
            ftpInfo.Add(
"UserName", userName);
            
string password = xmlDoc.DocumentElement.SelectSingleNode("//Password").InnerText;
            ftpInfo.Add(
"Password", password);
            
string folderSize = xmlDoc.DocumentElement.SelectSingleNode("//FolderSize").InnerText;
            ftpInfo.Add(
"FolderSize", folderSize);
            
return ftpInfo;
        }

        
protected override void OnInit(EventArgs e)
        {
            
base.OnInit(e);
        }

        
protected override void CreateChildControls()
        {
            
base.CreateChildControls();
            
try
            {
                
if (null == this.updateLink)
                {
                    
this.updateLink = new LinkButton();
                }
                
string backUrl = String.Empty;
                
string webUrl = SPContext.Current.Web.Url;
                
string formUrl = String.Empty;

                
if(this.ControlMode == SPControlMode.Edit || this.ControlMode == SPControlMode.Display)
                {
                    
string webID = SPContext.Current.Web.ID.ToString();
                    
string webName = SPContext.Current.Web.Title;
                    
string webFolderName = webID + "_" + webName;
                    
string listID = SPContext.Current.ListId.ToString();
                    
string listName = SPContext.Current.List.Title;
                    
string listFolderName = listID + "_" + listName;
                    
string itemID = SPContext.Current.ItemId.ToString();
                    
//if item fold has been created, this field layouted as a html link, else this field layouted as a link button
                    if (ftpUtility.IsFolderOrFileExist(webFolderName, ""))
                    {
                        
//list folder has been created on FTP
                        if (ftpUtility.IsFolderOrFileExist(listFolderName, "/" + webFolderName))
                        {
                            
//item folder has been created
                            if (ftpUtility.IsFolderOrFileExist(itemID, "/" + webFolderName + "/" + listFolderName))
                            {
                                
long folderSize = ftpUtility.GetFolderSize("/" + webFolderName + "/" + listFolderName + "/" + itemID);
                                
string js = String.Empty;
                                
if (folderSize > this.folderMaxSize)
                                {
                                    js 
= "alert('This folder is full without any space, you cannot upload any file before you clean up it.');";
                                }
                                
else
                                {
                                    js 
= "window.open('" + this.ftpUtility.FTPUrl + "/" + webFolderName + "/" + listFolderName + "/" + itemID + "','','height=500,width=700,toolbar=yes,status=no');";
                                }
                                
this.fileLink.Attributes.Add("onclick", js);
                                js 
= "this.style.textDecoration = 'underline'; this.style.cursor='hand';";
                                
this.fileLink.Attributes.Add("onmouseover", js);
                                
this.fileLink.Attributes.Add("onmouseout""this.style.textDecoration = 'none'");
                                
this.fileLink.Text = "Attachment";
                                List
<string> fileList = ftpUtility.GetListDirectoryDetails("/" + webFolderName + "/" + listFolderName + "/" + itemID);
                                HtmlTableRow tableRow 
= null;
                                HtmlTableCell cell 
= null;
                                
foreach(string file in fileList)
                                {
                                    tableRow 
= new HtmlTableRow();
                                    cell 
= new HtmlTableCell();
                                    cell.Attributes.Add(
"Class""ms-vb");
                                    cell.InnerHtml 
="<a href='" + this.ftpUtility.FTPUrl + "/" + webFolderName + "/" + listFolderName + "/" + itemID + "/" + file + "'>" + file + "</a>";
                                    tableRow.Cells.Add(cell);
                                    
this.fileTable.Rows.Add(tableRow);
                                }
                                
this.Controls.Clear();
                                
this.Controls.Add(fileLink);
                                
this.Controls.Add(this.fileTable);
                            }
                            
else
                            {
                                
this.updateLink.Click += new EventHandler(updateLink_Click);
                                
this.updateLink.Text = "Attachment";
                                
this.Controls.Clear();
                                
this.Controls.Add(updateLink);
                            }
                        }
                        
else
                        {
                            
this.updateLink.Click += new EventHandler(updateLink_Click);
                            
this.updateLink.Text = "Attachment";
                            
this.Controls.Clear();
                            
this.Controls.Add(updateLink);
                        }
                    }
                    
else
                    {
                        
this.updateLink.Click += new EventHandler(updateLink_Click);
                        
this.updateLink.Text = "Attachment";
                        
this.Controls.Clear();
                        
this.Controls.Add(updateLink);
                    }
                }
                
else if (this.ControlMode == SPControlMode.New)
                {
                    
this.fileLink.Text = "Attachment(Please update and download files in edit page.)";
                    
this.Controls.Clear();
                    
this.Controls.Add(fileLink);
                }
            }
            
catch (Exception)
            {
                ;
            }
        }

        
protected void updateLink_Click(object sender, EventArgs e)
        { 
            
string webID = SPContext.Current.Web.ID.ToString();
            
string webName = SPContext.Current.Web.Title;
            
string webFolderName = webID + "_" + webName;
            
string listID = SPContext.Current.ListId.ToString();
            
string listName = SPContext.Current.List.Title;
            
string listFolderName = listID + "_" + listName;
            
string itemID = SPContext.Current.ItemId.ToString();
            
try
            {
                
if (ftpUtility.IsFolderOrFileExist(webFolderName, ""))
                {
                    
if (ftpUtility.IsFolderOrFileExist(listFolderName, "/" + webFolderName))
                    {
                        
if (ftpUtility.IsFolderOrFileExist(itemID, "/" + webFolderName + "/" + listFolderName))
                        {
                            
return;
                        }
                        
else
                        {
                            
this.ftpUtility.CreateFolder(webFolderName + "/" + listFolderName + "/" + itemID);
                        }
                    }
                    
else
                    {
                        
this.ftpUtility.CreateFolder(webFolderName + "/" + listFolderName);
                        
this.ftpUtility.CreateFolder(webFolderName + "/" + listFolderName + "/" + itemID);
                    }
                }
                
else
                {
                    
this.ftpUtility.CreateFolder(webFolderName);
                    
this.ftpUtility.CreateFolder(webFolderName + "/" + listFolderName);
                    
this.ftpUtility.CreateFolder(webFolderName + "/" + listFolderName + "/" + itemID);
                }
                
//Context.Response.Redirect(this.ftpUtility.FTPUrl + "/" + webFolderName + "/" + listFolderName + "/" + itemID);
                string js = "<script language=javascript>window.open('" + this.ftpUtility.FTPUrl + "/" + webFolderName + "/" + listFolderName + "/" + itemID + "','','height=500,width=700,toolbar=yes,status=no') </script>";
                Context.Response.Write(js);
            }
            
catch
            {
                
return;
            }
        }

        
protected override void Render(HtmlTextWriter output)
        {
            
base.Render(output);
            
if (this.ControlMode == SPControlMode.Display)
            {
                
string webID = SPContext.Current.Web.ID.ToString();
                
string webName = SPContext.Current.Web.Title;
                
string webFolderName = webID + "_" + webName;
                
string listID = SPContext.Current.ListId.ToString();
                
string listName = SPContext.Current.List.Title;
                
string listFolderName = listID + "_" + listName;
                
string itemID = SPContext.Current.ItemId.ToString();
                
if (ftpUtility.IsFolderOrFileExist(webFolderName, ""))
                {
                    
//list folder has been created on FTP
                    if (ftpUtility.IsFolderOrFileExist(listFolderName, "/" + webFolderName))
                    {
                        
//item folder has been created
                        if (ftpUtility.IsFolderOrFileExist(itemID, "/" + webFolderName + "/" + listFolderName))
                        {
                            
string uploadFileHref = "<a href='" + this.ftpUtility.FTPUrl + "/" + webFolderName + "/" + listFolderName + "/" + itemID + "'>Attachment</a>";
                            output.Write(uploadFileHref);
                        }
                        
else
                        {
                            output.Write(
"Please create file repository in edit page");
                        }
                    }
                }
            }
        }

        
public override void UpdateFieldValueInItem()
        {
            
this.EnsureChildControls();

            
try
            {
                
this.Value = this.updateLink.Text;
                
this.ItemFieldValue = this.Value;
            }
            
catch (Exception)
            {
                ;
            }
        }

        
public override object Value
        {
            
get
            {
                
this.EnsureChildControls();
                
if (this.updateLink != null)
                    
return "";
                
else
                    
return null;
            }
        }
    }

 

可以在代码中发现,在FTP上创建的文件夹按照"WebID/ListID/ItemID"的层次结构创建。避免了文件夹的重复创建以及附件的分类问题。

接下来可以创建一个.xml文件,将FTP server的地址,用户的ID和密码写入,当这些基础信息发生改变时,只要配置这个Xml文件即可而不需要修改代码。部署时将此XML文件放入 "系统目录\Windows\system32\inetsrv,以确保能够被我们的自定义字段程序访问。

部署完此字段,为任何一个List添加自定义字段,下面是效果图:

新建Item:

编辑Item:

点击Attachment链接,打开ftp目录,就可以上传下载属于此Item的附件了:

 

 

 

 安装文件可以在此下载:/Files/tonnie/AECSharePoint.Field.FileTransfer.rar

欢迎指正!谢谢!

 

posted on 2010-05-31 15:36  Tonnie  阅读(1639)  评论(6编辑  收藏  举报