2

I have a Document Library, with a lookup column referencing a row of a metadata list (custom).

I am trying to upload documents programmatically but I also want to add a row in this list and link it to the document that is just uploaded. How can I achieve this?

public static void Upload(string path)
        {
            using (SPSite site = new SPSite("http://localhost/"))
            using (SPWeb web = site.OpenWeb())
            {
                var folder = web.GetFolder("Documents");
                var files = folder.Files;

                var fStream = System.IO.File.OpenRead(path);
                var contents = new byte[fStream.Length];
                fStream.Read(contents, 0, (int)fStream.Length);
                fStream.Close();

                SPList list = web.Lists["Documents Data"];
                SPListItem listItem = list.AddItem();
                // ....
                listItem["Title"] = "test test";

                listItem.Update();

                var documentMetadata = new System.Collections.Hashtable { { "Data", listItem } };


                // .... ??
     }
  • 1
    Do you need a second list for the metadata? Document libraries can have additional columns (or preferably a content type) to hold the metadata. – Paul Schaeflein Apr 7 '15 at 1:37
  • Yes, i actually do a second and a third list to store metadata to create some kind of relational database with lists. – enb081 Apr 7 '15 at 7:08
2
+50

The following example demonstrates how to:

  • create a list item in DocumentsMetadata list
  • upload file into Documents library and set it properties, in particular set Lookup field value to newly created item from DocumentsMetadata list

Example:

using (var site = new SPSite(siteUrl))
{
    using (var web = site.OpenWeb())
    {

       //1.Create meta item
       var metaList = web.Lists.TryGetList("DocumentsMetadata");
       var listItem = metaList.AddItem();
       listItem["Title"] = "Documents info";
       listItem.Update();

       //2. upload file and set properties
       var list = web.Lists.TryGetList("Documents");
       var fileContent = System.IO.File.ReadAllBytes(fileName);
       var fileUrl = Path.GetFileName(fileName);
       var fileProperties = new Hashtable();
       fileProperties["Metadata"] = listItem.ID;  //set Metadata Lookup Id 
       var uploadFile = list.RootFolder.Files.Add(fileUrl, fileContent, fileProperties, true);

   }
}

Update

using (var site = new SPSite(siteUrl))
{
    using (var web = site.OpenWeb())
    {
                var list = web.Lists.TryGetList("Documents");
                var metaList = web.Lists.TryGetList("DocumentsMetadata");
                var fileUrl = Path.GetFileName(fileName);
                var file = web.GetFile(SPUrlUtility.CombineUrl(list.RootFolder.Url, fileUrl));
                var fileContent = System.IO.File.ReadAllBytes(fileName);
                var refItemId = -1;

                if (file.Exists)
                {
                    //retrieve existing meta item 
                    var refLookupVal =  new SPFieldLookupValue(file.ListItemAllFields["Metadata"].ToString());
                    refItemId = refLookupVal.LookupId;
                    var listItem = metaList.GetItemById(refItemId);
                    //...
                    listItem.Update();
                }
                else  /* New one? */
                {
                    //Create meta item
                    var listItem = metaList.AddItem();
                    listItem["Title"] = "Documents info";
                    listItem.Update();
                    refItemId = listItem.ID;
                }

                //upload file and set properties
                var fileProperties = new Hashtable();
                fileProperties["Metadata"] = refItemId; //set Metadata Lookup Id 
                var uploadFile = list.RootFolder.Files.Add(fileUrl, fileContent, fileProperties, true);


   }
}
  • 1
    I am trying it right now. – enb081 Apr 8 '15 at 12:26
  • This works fine, but if I upload programically the same document twice, it will not update its metadata list item, but i will always add a new item instead and link it to the document. – enb081 Apr 8 '15 at 13:28
  • 1
    See the updated answer, it demonstrates how to handle the case if file already exists – Vadim Gremyachev Apr 8 '15 at 13:59
1

You just need to loop through all documents in that Library and get the latest document using order by in caml query like below after fStream.Close().

Code sample for caml query

Microsoft.SharePoint.Client.CamlQuery camlQuery = new CamlQuery();
    camlQuery.ViewXml =
       @"<View>
           <Query>
                <OrderBy><FieldRef Name="Modified" /></OrderBy>
            </Query>
       </View>"; 
   ListItemCollection listItems = spList.GetItems(camlQuery);
    clientContext.Load(listItems); 
   clientContext.ExecuteQuery();

Now you can loop through all the items & get the first item which is recently uploaded & get the URL by

SPListItem item = ...;
string absUrl = (string) item[SPBuiltInFieldId.EncodedAbsUrl];

Now you can use

Hashtable MetaData = new Hashtable();
MetaData = retornaMetadata(MetaData);
SPFileCollection destFiles = web.GetFolder("Folder Path").Files;

Files.Add(Path.GetFileName(inputFile.PostedFile.FileName), inputFile.PostedFile.InputStream, MetaData, true);

private Hashtable retornaMetadata(Hashtable MetaData)
{
  MetaData.Add("Column Name", "Metadata Value");
  return MetaData;
}
  • Is it safe? What if many users are uploading documents at the same time? – enb081 Apr 6 '15 at 13:22
  • As your code itself uploading document than there is no chance of conflict of time of upload. we are going to upload the document & get that document information instantly. – Hardik Apr 6 '15 at 13:33
  • Have you got any resolution? – Hardik Apr 7 '15 at 8:34
  • I am not convinced that there is absolutely no chance of time conflict, as the same code will be executed by many users in the same time. – enb081 Apr 8 '15 at 13:35
1

Use this code snippet to create a new file (add to folder)

SPFile spfile = spfolder.Files.Add("Sample.docx", fileStream, true);
spFile.Item["Title"] = "Sample document";
spFile.Item.Update();

In this case you will get the item id through

spFile.Item.Id;
  • How does this answer my question? – enb081 Apr 8 '15 at 8:58
  • Now you have the ID of newly uploaded file so you can add it as a lookup to item in the list. – luccio Apr 8 '15 at 12:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.