SharePoint Developer Center >
SharePoint Products and Technologies Forums
>
SharePoint - Development and Programming
>
Download attachment from MOSS document lobrary programatically based on a custom field
Download attachment from MOSS document lobrary programatically based on a custom field
- Hello,
How can I programatically download attachment from MOSS document library using either MOSS web services or Object model?
I want to download the file based on FileName field.User will specify the file name when uploading the file.The file names will be unique.
There will be only one attachment per document library item.
Can the same SP objects can be used for downloading attahments for Lists as well as document library?
Answers
- you can do this by both ways. Webservice is more complicated:
firsyoz take use of the Lists.asmx-Service and get all document of the user. Afterwards you calculate the documents URL, get them by a WebRequest and store them locally
XmlDocument xmlDoc = new XmlDocument(); XmlNode ndQuery = xmlDoc.CreateNode(XmlNodeType.Element, "Query", ""); XmlNode ndViewFields = xmlDoc.CreateNode(XmlNodeType.Element, "ViewFields", ""); XmlNode ndQueryOptions = xmlDoc.CreateNode(XmlNodeType.Element, "QueryOptions", ""); ndQueryOptions.InnerXml = "<IncludeMandatoryColumns>FALSE</IncludeMandatoryColumns>" + "<DateInUtc>TRUE</DateInUtc>" + "<ViewAttributes Scope='RecursiveAll' />"; ndQuery.InnerXML += = @"<Where><Eq><FieldRef Name=\"Author\" /><Value Type=\"User\">domain\username</Value></Eq></Where><OrderBy><FieldRef Name=\"Modified\" Ascending=\"False\" /></OrderBy>"; Lists wsSourceList = new Lists(); wsSourceList.Url = "http://server/site/Lists.asmx"; wsSourceList.Credentials = System.Net.CredentialCache.DefaultCredentials; XmlNode ndListSourceItems = wsSourceList.GetListItems( "MyDocLib", viewName, ndQuery, ndViewFields, rowLimit, ndQueryOptions, null ); foreach (XmlNode sourceItem in ndListSourceItems.ChildNodes[1].ChildNodes) { if (!(sourceItem is XmlWhitespace)) { if (!sourceItem.Attributes["ows_ContentType"].Value.Equals("Folder")) { String sourceURL = sourceItem.Attributes["ows_FileRef"].Value; sourceURL = "http:server/site/" + sourceURL.Substring(sourceURL.IndexOf("#") + 1); String sourceName = sourceUrl.Substring(sourceUrl.LastIndexof("/")+1); System.Net.WebRequest requestForAttachment = System.Net.FileWebRequest.Create(sourceURL); requestForAttachment.Credentials = System.Net.CredentialCache.DefaultCredentials; using (Stream httpStream= requestForAttachment.GetResponse().GetResponseStream()) { StreamReader reader = new StreamReader(httpStream); using (FileStream outFile = new FileStream("c:\\"+sourceName, FileAccess.Write, FileMode.Create)) { byte[] buff = new byte[1024]; int len = 0; while ( (len = reader.Read(buff, 0,1024) >0)) outFile.Write(buff, 0,len); } } } } }
- Marked As Answer byCharlie WuModeratorWednesday, November 11, 2009 2:10 AM
- Based on your needs you should probably just store the attachment/file as a document in a document librarry. The out of the box web services do not support retrieving atttachments to list items based on the name of the attachment. If you store the attachment as a document in a document library you will be able to retrieve it various ways with the url of the document using either webdav, copy web service or rpc.
http://sharepointfieldnotes.blogspot.com/2009/09/downloading-content-from-sharepoint-let.html
You could create your own web service that takes the name of the attachment but you will also need to pass in the item id that it is attached to. Otherwise you wlll have to loop through all the listitems and check their attachements collection.
certdev.com- Marked As Answer byCharlie WuModeratorWednesday, November 11, 2009 2:10 AM
- Steve, not really out of the box but you can do it this way
//get the IDs of the appopriate ListItem and iterate with them through this code XmlNode attachments = listsWebServiceSource.GetAttachmentCollection("Sourcelistname", itemID); foreach (XmlNode ndAttachment in attachments.ChildNodes){ String SourcePath = ndAttachment.InnerText; System.Net.WebRequest requestForAttachment = System.Net.FileWebRequest.Create(sourcePath); requestForAttachment.Credentials = System.Net.CredentialCache.DefaultCredentials; using (Stream httpStream= requestForAttachment.GetResponse().GetResponseStream()) <br/> { StreamReader reader = new StreamReader(httpStream); //read attachment as stream binary and save it as file or store it somewhere else } }
- Marked As Answer byCharlie WuModeratorWednesday, November 11, 2009 2:10 AM
using (SPWeb oWebsiteRoot = SPContext.Current.Site.RootWeb) { SPList oList = oWebsiteRoot.Lists["<em>[DocumentLibraryName]</em>"]; SPQuery oQuery = new SPQuery(); oQuery.Query = "<Where><Eq><FieldRef Name='Title'/>" + "<Value Type='Text'><em>[uniqueName]</</em>Value></Eq></Where>"; SPListItemCollection collListItems = oList.GetItems(oQuery); foreach (SPListItem oListItem in collListItems) { if (oListitem.File != null) { Stream streamFileContent = oLIstItem.File.OpenBinary(); //do with the stream what you want } } }
- Marked As Answer byCharlie WuModeratorWednesday, November 11, 2009 2:10 AM
All Replies
- you can do this by both ways. Webservice is more complicated:
firsyoz take use of the Lists.asmx-Service and get all document of the user. Afterwards you calculate the documents URL, get them by a WebRequest and store them locally
XmlDocument xmlDoc = new XmlDocument(); XmlNode ndQuery = xmlDoc.CreateNode(XmlNodeType.Element, "Query", ""); XmlNode ndViewFields = xmlDoc.CreateNode(XmlNodeType.Element, "ViewFields", ""); XmlNode ndQueryOptions = xmlDoc.CreateNode(XmlNodeType.Element, "QueryOptions", ""); ndQueryOptions.InnerXml = "<IncludeMandatoryColumns>FALSE</IncludeMandatoryColumns>" + "<DateInUtc>TRUE</DateInUtc>" + "<ViewAttributes Scope='RecursiveAll' />"; ndQuery.InnerXML += = @"<Where><Eq><FieldRef Name=\"Author\" /><Value Type=\"User\">domain\username</Value></Eq></Where><OrderBy><FieldRef Name=\"Modified\" Ascending=\"False\" /></OrderBy>"; Lists wsSourceList = new Lists(); wsSourceList.Url = "http://server/site/Lists.asmx"; wsSourceList.Credentials = System.Net.CredentialCache.DefaultCredentials; XmlNode ndListSourceItems = wsSourceList.GetListItems( "MyDocLib", viewName, ndQuery, ndViewFields, rowLimit, ndQueryOptions, null ); foreach (XmlNode sourceItem in ndListSourceItems.ChildNodes[1].ChildNodes) { if (!(sourceItem is XmlWhitespace)) { if (!sourceItem.Attributes["ows_ContentType"].Value.Equals("Folder")) { String sourceURL = sourceItem.Attributes["ows_FileRef"].Value; sourceURL = "http:server/site/" + sourceURL.Substring(sourceURL.IndexOf("#") + 1); String sourceName = sourceUrl.Substring(sourceUrl.LastIndexof("/")+1); System.Net.WebRequest requestForAttachment = System.Net.FileWebRequest.Create(sourceURL); requestForAttachment.Credentials = System.Net.CredentialCache.DefaultCredentials; using (Stream httpStream= requestForAttachment.GetResponse().GetResponseStream()) { StreamReader reader = new StreamReader(httpStream); using (FileStream outFile = new FileStream("c:\\"+sourceName, FileAccess.Write, FileMode.Create)) { byte[] buff = new byte[1024]; int len = 0; while ( (len = reader.Read(buff, 0,1024) >0)) outFile.Write(buff, 0,len); } } } } }
- Marked As Answer byCharlie WuModeratorWednesday, November 11, 2009 2:10 AM
- Based on your needs you should probably just store the attachment/file as a document in a document librarry. The out of the box web services do not support retrieving atttachments to list items based on the name of the attachment. If you store the attachment as a document in a document library you will be able to retrieve it various ways with the url of the document using either webdav, copy web service or rpc.
http://sharepointfieldnotes.blogspot.com/2009/09/downloading-content-from-sharepoint-let.html
You could create your own web service that takes the name of the attachment but you will also need to pass in the item id that it is attached to. Otherwise you wlll have to loop through all the listitems and check their attachements collection.
certdev.com- Marked As Answer byCharlie WuModeratorWednesday, November 11, 2009 2:10 AM
- Steve, not really out of the box but you can do it this way
//get the IDs of the appopriate ListItem and iterate with them through this code XmlNode attachments = listsWebServiceSource.GetAttachmentCollection("Sourcelistname", itemID); foreach (XmlNode ndAttachment in attachments.ChildNodes){ String SourcePath = ndAttachment.InnerText; System.Net.WebRequest requestForAttachment = System.Net.FileWebRequest.Create(sourcePath); requestForAttachment.Credentials = System.Net.CredentialCache.DefaultCredentials; using (Stream httpStream= requestForAttachment.GetResponse().GetResponseStream()) <br/> { StreamReader reader = new StreamReader(httpStream); //read attachment as stream binary and save it as file or store it somewhere else } }
- Marked As Answer byCharlie WuModeratorWednesday, November 11, 2009 2:10 AM
- Thanks.I will explain the process at my end in details.
1 : User will upload the file to sharepoint Document library (as per your suggestion) with a unique file name using an asp.net utility that I am creating for them.The unique file name will be generated by Oracle and File Name will be stored in the Oracle DB.
2:When I have to retreive the FIle from MOSS, I will get the FileName field from Oracle table and based on the file name field I need to download the attachment.
For achieving point 2, since you mentioned that I cannot do it based on the fileName field , here is what i am planning to do.
when my utility for uploading the file to MOSS uploads the file , as the next step, it will save the file name/COmplete URL and the List Item ID to a custom SQL table.
When I am retreiving the file, I will get the file name from Oracle and match that file name in the SQL table and get the item ID.Based on that item id I will retreive the attachment.
Does this process look fine to you?Or do you think there is a better way? - I think that is fine. I am still confused as to why you are using a single attachment versus just putting the document in a document library.
certdev.com - I did not understand "why you are using a single attachment versus just putting the document in a document library."
I am planning to upload the document to the document library.I will also upload the file Name and Document Library List ID to SQl server to match against later. - Also,
I want to upload files to document library and also add 5-6 metadata field to it programatically .What are the ways I can do it?
Are there any out of Box MOSS web service / Object model that will allow me to upload document as well as metadata?
Also, I need to get the Document library ID back as response.
Please suggest. - Hi Rachana, For downloading file from a MOSS document library you can use SPQuery class with your unique file name to retrieve document library item. Once you have item object you can use SPFile object to download file. I will send you code snippets later.
- Proposed As Answer byHereICome SharePoint Wednesday, November 11, 2009 12:45 AM
- Hello HereICome SharePoint ,
Could you find time to send me the code snippets.I need it urgently. using (SPWeb oWebsiteRoot = SPContext.Current.Site.RootWeb) { SPList oList = oWebsiteRoot.Lists["<em>[DocumentLibraryName]</em>"]; SPQuery oQuery = new SPQuery(); oQuery.Query = "<Where><Eq><FieldRef Name='Title'/>" + "<Value Type='Text'><em>[uniqueName]</</em>Value></Eq></Where>"; SPListItemCollection collListItems = oList.GetItems(oQuery); foreach (SPListItem oListItem in collListItems) { if (oListitem.File != null) { Stream streamFileContent = oLIstItem.File.OpenBinary(); //do with the stream what you want } } }
- Marked As Answer byCharlie WuModeratorWednesday, November 11, 2009 2:10 AM


