I need to upload a file using c# console app in a sharepoint library. I manage to upload it to the parent library only. But the requirement is to upload it on its sub folder.
So here's the Folder Structure:
Root Folder
-Sub Folder 1
---Sub Folder 2
----Sub Folder 3
I need to upload it in Sub Folder 3. Right now, I'm only able to upload on the Root Folder.
It throws an error when I tried to input the Sub Folder 3 in the GetByTitle method, but when it's the root folder, it is succeeding to upload.
Here's my code.
using (ClientContext clientContext = new ClientContext(siteURL))
{
clientContext.Credentials = new System.Net.NetworkCredential(#"username", "password", "domain");
var web = clientContext.Web;
// Create the new file
var newFile = new FileCreationInformation();
newFile.Content = System.IO.File.ReadAllBytes(#"C:\filepath\test.xlsx");
newFile.Overwrite = true;
newFile.Url = "Test Upload.xlsx";
List list = web.Lists.GetByTitle("Service Oriented Architecture (SOA)");
clientContext.Load(list);
clientContext.ExecuteQuery();
clientContext.Load(list.RootFolder);
clientContext.Load(list.RootFolder.Folders);
clientContext.ExecuteQuery();
foreach (Folder SubFolder in list.RootFolder.Folders)
{
if (SubFolder.Name.Equals("07 - SOA Environment"))
{
//What's next?
}
}
}
There are several options how to specify sub folder while uploading the file using CSOM
There are two assumptions about the provided solutions below:
The library name(url) is Documents and has the following folder structure:
Folder/Sub Folder/Sub Sub Folder/Sub Sub Sub Folder/
Folder structure already exists
Using FileCreationInformation.Url property
Use FileCreationInformation.Url property to specify the folder url for a uploaded file.
The following example demonstrates how to specify relative url (a slightly modified version of your example, the main difference comes in specifying FileCreationInformation.Url)
var uploadFilePath = #"c:\tmp\SharePoint User Guide.docx";
var fileCreationInfo = new FileCreationInformation
{
Content = System.IO.File.ReadAllBytes(uploadFilePath),
Overwrite = true,
Url = Path.Combine("Documents/Folder/Sub Folder/Sub Sub Folder/Sub Sub Sub Folder/", Path.GetFileName(uploadFilePath))
};
var list = context.Web.Lists.GetByTitle("Root Folder");
var uploadFile = list.RootFolder.Files.Add(fileCreationInfo);
context.Load(uploadFile);
context.ExecuteQuery();
Using Web.GetFolderByServerRelativeUrl method
Use Web.GetFolderByServerRelativeUrl method to retrieve a folder where file have to be uploaded:
public static void UploadFile(ClientContext context,string uploadFolderUrl, string uploadFilePath)
{
var fileCreationInfo = new FileCreationInformation
{
Content = System.IO.File.ReadAllBytes(uploadFilePath),
Overwrite = true,
Url = Path.GetFileName(uploadFilePath)
};
var targetFolder = context.Web.GetFolderByServerRelativeUrl(uploadFolderUrl);
var uploadFile = targetFolder.Files.Add(fileCreationInfo);
context.Load(uploadFile);
context.ExecuteQuery();
}
Usage
using (var ctx = new ClientContext(webUri))
{
ctx.Credentials = credentials;
UploadFile(ctx,"Documents/Folder/Sub Folder/Sub Sub Folder/Sub Sub Sub Folder",filePath);
}
You need to get sub folder within folder. like below
docs.RootFolder.SubFolders
Remaining things is same, just need to add in same folder.
try to go into folder like below
docs.Folders["FolderName"]
Related
I'm trying to upload a file to SharePoint Online and I got this sample code:
var uploadFile = list
.RootFolder
.Folders
.GetByPath(ResourcePath.FromDecodedUrl("A"))
.Files
.Add(newFile);
ctx.Load(uploadFile);
await ctx.ExecuteQueryAsync();
Which works perfectly fine, so everything around it works. But apparently this snippet
var uploadFile = list
.RootFolder
.Folders
.GetByPath(ResourcePath.FromDecodedUrl("A/B"))
.Files
.Add(newFile);
ctx.Load(uploadFile);
await ctx.ExecuteQueryAsync();
Throws System.IO.DirectoryNotFoundException even though both directories exist. So how can I upload a file to the subdirectory "B"?
Try to upload file like this:
public static void UploadFile(ClientContext context,string uploadFolderUrl, string uploadFilePath)
{
var fileCreationInfo = new FileCreationInformation
{
Content = System.IO.File.ReadAllBytes(uploadFilePath),
Overwrite = true,
Url = Path.GetFileName(uploadFilePath)
};
var targetFolder = context.Web.GetFolderByServerRelativeUrl(uploadFolderUrl);
var uploadFile = targetFolder.Files.Add(fileCreationInfo);
context.Load(uploadFile);
context.ExecuteQuery();
}
using (var ctx = new ClientContext(webUri))
{
ctx.Credentials = credentials;
UploadFile(ctx,"LibName/FolderName/Sub Folder Name/Sub Sub Folder Name/Sub Sub Sub Folder Name",filePath);
}
Please check out another similiar thread here:
Alternative Save/OpenBinaryDirect methods for CSOM for SharePoint Online
This is similar to my previous question:
Downloading images from publicly shared folder on Dropbox
I have this piece of code (simplified version) that needs to download all images from publicly shared folder and all sub-folders.
using Dropbox.Api;
using Dropbox.Api.Files;
...
// AccessToken - get it from app console
// FolderToDownload - https://www.dropbox.com/sh/{unicorn_string}?dl=0
using (var dbx = new DropboxClient(_dropboxSettings.AccessToken))
{
var sharedLink = new SharedLink(_dropboxSettings.FolderToDownload);
var sharedFiles = await dbx.Files.ListFolderAsync(path: "", sharedLink: sharedLink);
// var sharedFiles = await dbx.Files.ListFolderAsync(path: "", sharedLink: sharedLink, recursive: true);
// "recursive: true" throws: Error in call to API function "files/list_folder": Recursive list folder is not supported for shared link.
foreach (var entry in sharedFiles.Entries)
{
if (entry.IsFile)
{
var link = await dbx.Sharing.GetSharedLinkFileAsync(url: _dropboxSettings.FolderToDownload, path: "/" + entry.Name);
var byteArray = await link.GetContentAsByteArrayAsync();
}
if (entry.IsFolder)
{
var subFolder = entry.AsFolder;
// var folderContent = await dbx.Files.ListFolderAsync(path: subFolder.Id);
// var subFolderSharedLink = new SharedLink(???);
}
}
}
How do I list entries of all sub-folders?
For any given subfolder, to list its contents, you'll need to call back to ListFolderAsync again, using the same sharedLink value, but supplying a path value for the subfolder, relative to the root folder for the shared link.
For example, if you list the contents of the folder shared link, and one of the entries is a folder with the name "SomeFolder", to then list the contents of "SomeFolder", you would need to make a call like:
await dbx.Files.ListFolderAsync(path: "/SomeFolder", sharedLink: sharedLink);
I am trying to open a multipage HTML web page (i.e. test.html, test.css and test.js) which has been downloaded dynamically (thefore can't use assets) and stored in the apps internal storage (Xamarin.Essentials.FileSystem.AppDataDirectory).
The URL I am trying to use is as follows:
file:///data/user/0/com.test/files/HTML/Test.html
However I just get file not found.
var filesToDownload = new string[] { "http://myserver/test/test.html", "http://myserver/test/test.css" };
var directory = System.IO.Path.Combine(Xamarin.Essentials.FileSystem.AppDataDirectory, "HTML");
if (System.IO.Directory.Exists(directory))
{
System.IO.Directory.Delete(directory, true);
}
System.IO.Directory.CreateDirectory(directory);
using (var wc = new System.Net.WebClient())
{
foreach (var f in filesToDownload)
{
wc.DownloadFile(f, System.IO.Path.Combine(directory, System.IO.Path.GetFileName(f)));
}
}
var source = new UrlWebViewSource
{
Url = System.IO.Path.Combine("file://" + directory, "Test.html")
};
WebView1.Source = source;
There are several points you have to make sure:
1 Add the Xamarin.Essentials NuGet package to each project
2 http://myserver/test/test.html and http://myserver/test/test.css are existed and accessible.
3 The file name of webview source should be the same with the file name you have written to your storage. Not Test.html, but test.html
So
Url = System.IO.Path.Combine("file://" + directory, "Test.html") should be modified to
Url = System.IO.Path.Combine("file://" + directory, "test.html")
I'm looking for a way to move a folder and all it's contents to a different location in the same library using the Client Object Model for SharePoint 2010 (C#).
For example we have a folder for a project (say 12345) and it's URL is
http://sharepoint/site/library/2012/12345
where 2012 represents a year. I'd like to programmatically move the 12345 folder to a different year, say 2014 which probably exists already but may not.
I've searched around but the solutions I'm getting seem extremely complicated and relevant to moving folders to different site collections, I'm hoping because it's in the same library there might be a simpler solution? One idea I have is to rely on Explorer View instead of CSOM?
Thanks a lot!
There is no built-in method in SharePoint CSOM API for moving Folder with Files from one location into another.
The following class represents how to move files from source folder into destination folder:
public static class FolderExtensions
{
public static void MoveFilesTo(this Folder folder, string folderUrl)
{
var ctx = (ClientContext)folder.Context;
if (!ctx.Web.IsPropertyAvailable("ServerRelativeUrl"))
{
ctx.Load(ctx.Web, w => w.ServerRelativeUrl);
}
ctx.Load(folder, f => f.Files, f => f.ServerRelativeUrl, f => f.Folders);
ctx.ExecuteQuery();
//Ensure target folder exists
EnsureFolder(ctx.Web.RootFolder, folderUrl.Replace(ctx.Web.ServerRelativeUrl, string.Empty));
foreach (var file in folder.Files)
{
var targetFileUrl = file.ServerRelativeUrl.Replace(folder.ServerRelativeUrl, folderUrl);
file.MoveTo(targetFileUrl, MoveOperations.Overwrite);
}
ctx.ExecuteQuery();
foreach (var subFolder in folder.Folders)
{
var targetFolderUrl = subFolder.ServerRelativeUrl.Replace(folder.ServerRelativeUrl,folderUrl);
subFolder.MoveFilesTo(targetFolderUrl);
}
}
public static Folder EnsureFolder(Folder parentFolder, string folderUrl)
{
var ctx = parentFolder.Context;
var folderNames = folderUrl.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
var folderName = folderNames[0];
var folder = parentFolder.Folders.Add(folderName);
ctx.Load(folder);
ctx.ExecuteQuery();
if (folderNames.Length > 1)
{
var subFolderUrl = string.Join("/", folderNames, 1, folderNames.Length - 1);
return EnsureFolder(folder, subFolderUrl);
}
return folder;
}
}
Key points:
allows to ensure whether destination folder(s) exists
In case of nested folders, its structure is preserved while moving files
Usage
var srcFolderUrl = "/news/pages";
var destFolderUrl = "/news/archive/pages";
using (var ctx = new ClientContext(url))
{
var sourceFolder = ctx.Web.GetFolderByServerRelativeUrl(srcFolderUrl);
sourceFolder.MoveFilesTo(destFolderUrl);
sourceFolder.DeleteObject(); // delete source folder if nessesary
ctx.ExecuteQuery();
}
Just in case someone needs this translated to PnP PowerShell. It's not battle tested but works for me. Versions and metadata moved as well within the same library.
$list = Get-PnPList -Identity Documents
$web = $list.ParentWeb
$folder = Ensure-PnPFolder -Web $list.ParentWeb -SiteRelativePath "Shared Documents/MoveTo"
$tofolder = Ensure-PnPFolder -Web $list.ParentWeb -SiteRelativePath "Shared Documents/MoveTwo"
function MoveFolder
{
[cmdletbinding()]
Param (
$web,
$fromFolder,
$toFolder
)
$fromFolder.Context.Load($fromFolder.Files)
$fromFolder.Context.Load($fromFolder.Folders)
$fromFolder.Context.ExecuteQuery()
foreach ($file in $fromFolder.Files)
{
$targetFileUrl = $file.ServerRelativeUrl.Replace($fromFolder.ServerRelativeUrl, $toFolder.ServerRelativeUrl);
$file.MoveTo($targetFileUrl, [Microsoft.SharePoint.Client.MoveOperations]::Overwrite);
}
$fromFolder.Context.ExecuteQuery();
foreach ($subFolder in $fromFolder.Folders)
{
$targetFolderUrl = $subFolder.ServerRelativeUrl.Replace($fromFolder.ServerRelativeUrl, $toFolder.ServerRelativeUrl);
$targetFolderRelativePath = $targetFolderUrl.SubString($web.RootFolder.ServerRelativeUrl.Length)
$tofolder = Ensure-PnPFolder -Web $list.ParentWeb -SiteRelativePath $targetFolderRelativePath
MoveFolder -Web $web -fromFolder $subFolder -toFolder $tofolder
}
}
$web.Context.Load($web.RootFolder)
$web.Context.ExecuteQuery()
MoveFolder -Web $web -fromFolder $folder -toFolder $tofolder
$folder.DeleteObject()
$web.Context.ExecuteQuery()
Question Background:
Within my TF Server I have two folders, one is a simple 'HelloWorld.sln' in a folder called 'HelloWorldDev' and the other is a 'HelloWorld.sln' in a folder called 'HelloWorldQA'. Each folder contains its respective .cs files etc.
I want to checkout a file from the HelloWorld QA folder, replace - or update it - with a version from the HelloWorldDev folder with the same file name, then check this file back into the HelloWorldQA folder with the relevant changes.
Question:
I am very new to the TFS API so I'm not 100% if what I'm trying to ask is the correct way to proceed, or if its even possible. Can someone give me an example of achieving this?
Code so far:
string fileName = #"C:\Users\Me\Documents\TfsServer\HelloWorldQA\IHelloWorld.cs";
string fileNameQA = #"C:\Users\Me\Documents\TfsServer\HelloWorld\IHelloWorld.cs";
string uri = #"https://tfsServer.visualstudio.com/";
var workspaceInfo = Workstation.Current.GetLocalWorkspaceInfo(fileName);
var server = new TfsTeamProjectCollection(workspaceInfo.ServerUri);
var workspace = workspaceInfo.GetWorkspace(server);
workspace.PendEdit(fileName);
FileInfo fi = new FileInfo(fileName);
var workspaceInfoQA = Workstation.Current.GetLocalWorkspaceInfo(fileNameQA);
var serverQA = new TfsTeamProjectCollection(workspaceInfo.ServerUri);
var workspaceQA = workspaceInfo.GetWorkspace(serverQA);
workspace.PendEdit(fileNameQA);
FileInfo fiQA = new FileInfo(fileNameQA);
First, instead of using 2 workspaces, you can simply map both folders in the same workspace.
Then you're looking for a merge operation:
var sourcePath = workspace.GetServerItemForLocalItem(fileName);
var targetPath = workspace.GetServerItemForLocalItem(fileNameQA);
var getStatus = workspace.Merge(sourcePath, targetPath, null, null);
if (getStatus.NumUpdated > 0)
{
//OK
}