Through C#, I'm trying to download a file from SharePoint (SharePoint 2016). Below is the code I'm using:
site = new ClientContext(url);
//credential setting has no issues. So I am skipping it. I am using NetworkCredentials
site.Load(web);
site.ExecuteQuery();
List list = web.Lists.GetByTitle("Documents");
site.Load(list);
site.ExecuteQuery();
site.Load(list.RootFolder);
site.ExecuteQuery();
site.Load(list.RootFolder.Folders);
site.ExecuteQuery();
Folder folder = web.GetFolderByServerRelativeUrl(sharePointPath);
site.Load(folder);
site.ExecuteQuery();
site.Load(folder.Files);
site.ExecuteQuery();
While the last "site.ExecuteQuery()" is being executed, an exception is thrown:
ExceptionMessage: File not found
at Microsoft.SharePoint.Client.ClientRequest.ProcessResponseStream
But, there are files in that path and manually we are able to upload and download with the same credentials. URLs, Paths, etc have been double-checked and no issues with that.
When I print "folder.ItemCount", it is printing the correct no. of files in the folder. Only in ExecuteQuery for loading files, it is throwing exception.
Build settings: .NET framework 4.5 and x64
In other posts, people advised to change to .NET 3.5 but it was for SharePoint 2010. Further, changing it to 3.5 ends up in lot of build errors for me.
Please help in fixing this.
Here is the code snippet to download a file from SharePoint default Document library and save into a local folder:
static void Main(string[] args)
{
string siteUrl = "http://sp2016/sites/dev";
ClientContext clientContext = new ClientContext(siteUrl);
var list = clientContext.Web.Lists.GetByTitle("Documents");
var listItem = list.GetItemById(5);
clientContext.Load(list);
clientContext.Load(listItem, i => i.File);
clientContext.ExecuteQuery();
var fileRef = listItem.File.ServerRelativeUrl;
var fileInfo = Microsoft.SharePoint.Client.File.OpenBinaryDirect(clientContext, fileRef);
var fileName = Path.Combine(#"C:\Test", (string)listItem.File.Name);
using (var fileStream = System.IO.File.Create(fileName))
{
fileInfo.Stream.CopyTo(fileStream);
}
}
I was working with collection and above solution did not work for me, here is how I did so that it can help someone.
List list = web.Lists.GetByTitle("Events");
ListItemCollection listItems = list.GetItems(cmlqry);
context.Load(listItems);
context.ExecuteQuery();
if (listItems != null)
{
foreach (var listItem in listItems)
{
Console.WriteLine("Id: {0}, Title: {1}", listItem["ID"].ToString(), listItem["Title"].ToString());
context.Load(listItem.AttachmentFiles);
context.ExecuteQuery();
foreach (var file in listItem.AttachmentFiles)
{
Console.WriteLine("File: {0}", file.FileName);
var fileRef = file.ServerRelativeUrl;
var fileInfo = Microsoft.SharePoint.Client.File.OpenBinaryDirect(context, fileRef);
var fileName = Path.Combine(#"C:\temp\Events\", String.Format("{0}_{1}", listItem.Id, file.FileName));
using (var fileStream = System.IO.File.Create(fileName))
{
fileInfo.Stream.CopyTo(fileStream);
}
}
}
}
Related
I'm having quite the time trying to get this seemingly simplistic line of code to work using C#. Trying to get a list of all my files in my repo.
File structure below:
MyRepo
-directory_01
--myFile_01.jpg
--myFile_02.jpg
This line of code lists all my directories and works great:
var streamTask = client.GetStringAsync(https://myURL/api/v4/projects/myRepo/repository/tree?private_token=myToken"
According to the api, to get my files only I should use files/:file_path attribute or archive.<file extension> to get my files.
//Get all .jpg files
var streamTask = client.GetStringAsync(https://myURL/api/v4/projects/myRepo/repository/archive.jpg?private_token=myToken"
OR
//Get one file
var streamTask = client.GetStringAsync(https://myURL/api/v4/projects/myRepo/repository/files/directory_01%2FmyFile_01%2Ejpg?private_token=myToken"
//result: 404
When you this API you also need to pass the branch name
Change
var streamTask = client.GetStringAsync(https://myURL/api/v4/projects/myRepo/repository/files/directory_01%2FmyFile_01%2Ejpg?private_token=myToken"
To
var streamTask = client.GetStringAsync(https://myURL/api/v4/projects/myRepo/repository/files/directory_01%2FmyFile_01%2Ejpg?private_token=myToken&ref=<branch_name>"
Just in case anyone else runs into this issue, here's a way to do this:
// Get list of files***********
string treeUri = $"{project}tree?private_token={projectToken}&ref=master";
string treeData = await client.GetStringAsync(treeUri);
List<AssetEntry> json = System.Text.Json.JsonSerializer.Deserialize<List<AssetEntry>>(treeData);
Console.WriteLine("FILE LIST:\n");
foreach (var item in json)
{
Console.WriteLine(item.name + " " );
}
Although this works, it seems rather verbose. Is there a more terse way? Using CSOM and a C# .Net Framework application. Really just want to delete the folder and contents. Thanks.
public static void DeleteFileAndFolder(string file)
{
using (var context = Sharepoint.ClientContext)
{
context.Credentials = new NetworkCredential(
Sharepoint.ExtranetUserName,
Sharepoint.ExtrantPassword);
var web = context.Web;
var list = web.Lists.GetByTitle(Sharepoint.ListTitle);
var deleteFile = list.RootFolder.FindFiles(file).Single();
deleteFile.Context.Load(deleteFile.ListItemAllFields);
deleteFile.Context.ExecuteQuery();
var folderUrl = deleteFile.ListItemAllFields["FileDirRef"].ToString();
var folder = deleteFile.ListItemAllFields.ParentList.ParentWeb.GetFolderByServerRelativeUrl(folderUrl);
deleteFile.Context.Load(folder);
deleteFile.Context.ExecuteQuery();
deleteFile.DeleteObject();
folder.DeleteObject();
context.ExecuteQuery();
}
}
You don`t need to get list, you can get folder from web object, see sample to delete files in folder:
ClientContext ctx = GetCtx();
Folder rootFolder = ctx.Web.GetFolderByServerRelativePath(ResourcePath.FromDecodedUrl("your path here"));
ctx.Load(rootFolder, f => f.Files);
ctx.ExecuteQuery();
foreach (var file in rootFolder.Files)
{
file.DeleteObject();
}
ctx.ExecuteQuery();
The code below, is an attempt to get (download) files from a sharepoint.
If I try this on my local version, it works like a charm. I can select all items in the document library.
There are several methods I've tried, and I could post some of them here if you like. I can download corrupt files, but even when the link is wrong.
If I try this on the TeamSite in Office 365, I get an exception that my link is wrong. But I'm referring to the same site (instead of localhost/dev/ im referring to http://mysite.com/TeamSite/dev/). Any idea what the difference can be? Does Microsoft block something so external connections aren't allowed?
private void btnDownload_Click(object sender, EventArgs e)
{
if (comboBox1.Items.Count > 0 && comboBox1.SelectedIndex != -1)
{
SaveFileDialog dialog = new SaveFileDialog();
dialog.ShowDialog();
using (SPSite site = new SPSite("http://localhost/dev/"))
{
using (SPWeb web = site.OpenWeb())
{
SPFolder myLibrary = web.Folders["Management"];
foreach (SPFile file in myLibrary.Files)
{
if (file.Name == comboBox1.SelectedItem.ToString())
{
byte[] bytes = file.OpenBinary();
try
{
FileStream fs = new FileStream(dialog.FileName, FileMode.Create, FileAccess.ReadWrite);
BinaryWriter bw = new BinaryWriter(fs);
bw.Write(bytes);
bw.Close();
MessageBox.Show("File downloaded to: " + dialog.FileName);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
}
}
else
{
MessageBox.Show("Select file to download");
}
}
This is the Exception message:
The Web application at http://www.gtest.nl/TeamSite/ could not be found. Verify that you have typed the URL correctly. If the URL should be serving existing content, the system administrator may need to add a new request URL mapping to the intended application.
You can not connect to sharepoint site, deployed on another computer like this.
You should use Client Context
for example:
string siteUrl = "http://MyServer/sites/MySiteCollection";
ClientContext clientContext = new ClientContext(siteUrl);
Web oWebsite = clientContext.Web;
ListCollection collList = oWebsite.Lists;
clientContext.Load(collList);
clientContext.ExecuteQuery();
foreach (SP.List oList in collList)
{
Console.WriteLine("Title: {0} Created: {1}", oList.Title, oList.Created.ToString());
}
you could find more examples on Client Context here
There is allready an example of file download from sharepoint through clientContext.
I am using the method
File.SaveBinaryDirect
in Microsoft.SharePoint.Client to insert new documents in a Sharepoint Library. just wondering what is the most effective way of getting the Guids of those new records.
Well, you've just saved the file to a particular URL - get the File by that URL, and then use the ListItemAllFields property to get the ListItem that would contain those IDs
From here:
var FileSrvRelUrl = "/sub/doclib/Folder/File.doc";
using (var fileStream = new MemoryStream(new byte[100]))
{
Microsoft.SharePoint.Client.File.SaveBinaryDirect(clientContext, FileSrvRelUrl, fileStream, false);
}
var web = clientContext.Web;
var f = web.GetFileByServerRelativeUrl(FileSrvRelUrl);
var item = f.ListItemAllFields;
item["SomeField"] = "Value";
item.Update();
clientContext.Load(item, i=>i.Id);
clientContext.ExecuteQuery();
Could you help me for how to add a file to the Sharepoint document library? I found some articles in .NET, but I didn't get the complete concept of how to accomplish this.
I uploaded a file without metadata by using this code:
if (fuDocument.PostedFile != null)
{
if (fuDocument.PostedFile.ContentLength > 0)
{
Stream fileStream = fuDocument.PostedFile.InputStream;
byte[] byt = new byte[Convert.ToInt32(fuDocument.PostedFile.ContentLength)];
fileStream.Read(byt, 0, Convert.ToInt32(fuDocument.PostedFile.ContentLength));
fileStream.Close();
using (SPSite site = new SPSite(SPContext.Current.Site.Url))
{
using (SPWeb webcollection = site.OpenWeb())
{
SPFolder myfolder = webcollection.Folders["My Library"];
webcollection.AllowUnsafeUpdates = true;
myfolder.Files.Add(System.IO.Path.GetFileName(fuDocument.PostedFile.FileName), byt);
}
}
}
}
This code is working fine as is, but I need to upload a file with metadata. Please help me by editing this code if it is possible. I created 3 columns in my document library.
SPFolder.Files.Add returns a SPFile object
SPFile.Item returns an SPListItem object
You can then use SPlistItem["FieldName"] to access each field (see bottom of SPListItem link)
So adding this into your code (this is not tested, but you should get the idea)
SPFile file = myfolder.Files.Add(System.IO.Path.GetFileName(document.PostedFile.FileName);
SPListItem item = file.Item;
item["My Field"] = "Some value for your field";
item.Update()
There is also an overload where you can send in a hashtable with the metadata you want to add. For example:
Hashtable metaData = new Hashtable();
metaData.Add("ContentTypeId", "some CT ID");
metaData.Add("Your Custom Field", "Your custom value");
SPFile file = library.RootFolder.Files.Add(
"filename.fileextension",
bytearray,
metaData,
false);