Creating a file under nested folder in Sharepoint - c#

What's the best way to create a file under a nested folder in Sharepoint ?
My current method
public string CreateSPFile(string spServerURL, string spDocumentLibraryURL, string folder, string fileName, Stream fileStream, bool overwrite)
{
if (SPSite.Exists(new Uri(spServerURL)))
{
SPSite site = new SPSite(spServerURL);
SPWeb oWebsite = site.OpenWeb();
oWebsite.AllowUnsafeUpdates = true;
SPFolder spFolder = oWebsite.Folders[spDocumentLibraryURL];
if (!string.IsNullOrEmpty(folder))
{
spFolder.SubFolders[folder].Files.Add(fileName, fileStream, overwrite);
}
else
{
SPFileCollection files = spFolder.Files;
spFolder.Files.Add(fileName, fileStream, overwrite);
}
oWebsite.AllowUnsafeUpdates = false;
site.Close();
}
}
As you can see, if I want to create a file under nested folder, i need to modified my codes.
What will be better way to handle this kind of saving nested folder situation?
According to my project structure, the file can be like /DocumentLibrary/Folder1/Folder2/Folder3/File.txt.

You can load a folder by its server relative URL:
SPFolder folder = web.GetFolder("/DocumentLibrary/Folder1/Folder2/Folder3/");
With this approach you do not have to load folder by folder and your code works with n folder levels.
I've updated your code sample and added some comments regarding SharePoint best practices:
public string CreateSPFile(string spServerURL, string spDocumenttargetUrl, string folder, string fileName, Stream fileStream, bool overwrite)
{
// I suggest skip this pre check since it internally opens a new site object
// If you have to silenlty ignore non-existant SPSite you should catch a FileNotFoundException.
if (SPSite.Exists(new Uri(spServerURL)))
{
// use the using construct to safely dispose the opened SPSite object
using (SPSite site = new SPSite(spServerURL))
{
// SPWeb object opened with SPSite.OpenWeb() have to be disposed as well
using (SPWeb web = site.OpenWeb())
{
web.AllowUnsafeUpdates = true;
string targetUrl = SPUrlUtility.CombineUrl(web.ServerRelativeUrl, spDocumenttargetUrl);
if (!String.IsNullOrEmpty(folder))
{
targetUrl = SPUrlUtility.CombineUrl(targetUrl, folder);
}
SPFolder target = web.GetFolder(target);
SPFileCollection files = target.Files;
target.Files.Add(fileName, fileStream, overwrite);
// no need to revert AllowUnsafeUpdates for newly opened webs
// web.AllowUnsafeUpdates = false;
}
}
}
}

For uploading a file into a nested folder you could consider the following approach:
ensure the target folder exist using the method EnsureFolder provided below
upload a file using SPFileCollection.Add method
How to ensure a nested Folder exist using SharePoint SSOM
internal static class SPWebExtensions
{
/// <summary>
/// Ensure SPFolder
/// </summary>
/// <param name="web"></param>
/// <param name="listTitle"></param>
/// <param name="folderUrl"></param>
/// <returns></returns>
public static SPFolder EnsureFolder(this SPWeb web, string listTitle, string folderUrl)
{
if (string.IsNullOrEmpty(folderUrl))
throw new ArgumentNullException("folderUrl");
var list = web.Lists.TryGetList(listTitle);
return CreateFolderInternal(list, list.RootFolder, folderUrl);
}
private static SPFolder CreateFolderInternal(SPList list, SPFolder parentFolder, string folderUrl)
{
var folderNames = folderUrl.Split(new char[] {'/'}, StringSplitOptions.RemoveEmptyEntries);
var folderName = folderNames[0];
var curFolder =
parentFolder.SubFolders.Cast<SPFolder>().FirstOrDefault( f => System.String.Compare(f.Name, folderName, System.StringComparison.OrdinalIgnoreCase) == 0);
if (curFolder == null)
{
var folderItem = list.Items.Add(parentFolder.ServerRelativeUrl, SPFileSystemObjectType.Folder,
folderName);
folderItem.SystemUpdate();
curFolder = folderItem.Folder;
}
if (folderNames.Length > 1)
{
var subFolderUrl = string.Join("/", folderNames, 1, folderNames.Length - 1);
return CreateFolderInternal(list, curFolder, subFolderUrl);
}
return curFolder;
}
}
Gist: EnsureFolder.cs
The following example demonstrates how to ensure the following folder structure exist under Documents library and upload a file into it:
Orders
|
A --
|
A1
Example:
var targetFolder = web.EnsureFolder("Documents", "Orders3/A/A1");
var fileContent = System.IO.File.ReadAllBytes(fileName);
var fileUrl = Path.GetFileName(fileName);
targetFolder.Files.Add(fileUrl, fileContent);

Related

How can I change the file name use c#? [duplicate]

How do I rename a file using C#?
Take a look at System.IO.File.Move, "move" the file to a new name.
System.IO.File.Move("oldfilename", "newfilename");
System.IO.File.Move(oldNameFullPath, newNameFullPath);
In the File.Move method, this won't overwrite the file if it is already exists. And it will throw an exception.
So we need to check whether the file exists or not.
/* Delete the file if exists, else no exception thrown. */
File.Delete(newFileName); // Delete the existing file if exists
File.Move(oldFileName,newFileName); // Rename the oldFileName into newFileName
Or surround it with a try catch to avoid an exception.
Just add:
namespace System.IO
{
public static class ExtendedMethod
{
public static void Rename(this FileInfo fileInfo, string newName)
{
fileInfo.MoveTo(fileInfo.Directory.FullName + "\\" + newName);
}
}
}
And then...
FileInfo file = new FileInfo("c:\test.txt");
file.Rename("test2.txt");
You can use File.Move to do it.
First solution
Avoid System.IO.File.Move solutions posted here (marked answer included).
It fails over networks. However, copy/delete pattern works locally and over networks. Follow one of the move solutions, but replace it with Copy instead. Then use File.Delete to delete the original file.
You can create a Rename method to simplify it.
Ease of use
Use the VB assembly in C#.
Add reference to Microsoft.VisualBasic
Then to rename the file:
Microsoft.VisualBasic.FileIO.FileSystem.RenameFile(myfile, newName);
Both are strings. Note that myfile has the full path. newName does not.
For example:
a = "C:\whatever\a.txt";
b = "b.txt";
Microsoft.VisualBasic.FileIO.FileSystem.RenameFile(a, b);
The C:\whatever\ folder will now contain b.txt.
You can copy it as a new file and then delete the old one using the System.IO.File class:
if (File.Exists(oldName))
{
File.Copy(oldName, newName, true);
File.Delete(oldName);
}
public void RenameFile(string filePath, string newName)
{
FileInfo fileInfo = new FileInfo(filePath);
fileInfo.MoveTo(fileInfo.Directory.FullName + "\\" + newName);
}
NOTE: In this example code we open a directory and search for PDF files with open and closed parenthesis in the name of the file. You can check and replace any character in the name you like or just specify a whole new name using replace functions.
There are other ways to work from this code to do more elaborate renames but my main intention was to show how to use File.Move to do a batch rename. This worked against 335 PDF files in 180 directories when I ran it on my laptop. This is spur of the moment code and there are more elaborate ways to do it.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BatchRenamer
{
class Program
{
static void Main(string[] args)
{
var dirnames = Directory.GetDirectories(#"C:\the full directory path of files to rename goes here");
int i = 0;
try
{
foreach (var dir in dirnames)
{
var fnames = Directory.GetFiles(dir, "*.pdf").Select(Path.GetFileName);
DirectoryInfo d = new DirectoryInfo(dir);
FileInfo[] finfo = d.GetFiles("*.pdf");
foreach (var f in fnames)
{
i++;
Console.WriteLine("The number of the file being renamed is: {0}", i);
if (!File.Exists(Path.Combine(dir, f.ToString().Replace("(", "").Replace(")", ""))))
{
File.Move(Path.Combine(dir, f), Path.Combine(dir, f.ToString().Replace("(", "").Replace(")", "")));
}
else
{
Console.WriteLine("The file you are attempting to rename already exists! The file path is {0}.", dir);
foreach (FileInfo fi in finfo)
{
Console.WriteLine("The file modify date is: {0} ", File.GetLastWriteTime(dir));
}
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.Read();
}
}
}
None of the answers mention writing a unit testable solution. You could use System.IO.Abstractions as it provides a testable wrapper around FileSystem operations, using which you can create a mocked file system objects and write unit tests.
using System.IO.Abstractions;
IFileInfo fileInfo = _fileSystem.FileInfo.FromFileName("filePathAndName");
fileInfo.MoveTo(Path.Combine(fileInfo.DirectoryName, newName));
It was tested, and it is working code to rename a file.
Use:
using System.IO;
string oldFilePath = #"C:\OldFile.txt"; // Full path of old file
string newFilePath = #"C:\NewFile.txt"; // Full path of new file
if (File.Exists(newFilePath))
{
File.Delete(newFilePath);
}
File.Move(oldFilePath, newFilePath);
Use:
public static class FileInfoExtensions
{
/// <summary>
/// Behavior when a new filename exists.
/// </summary>
public enum FileExistBehavior
{
/// <summary>
/// None: throw IOException "The destination file already exists."
/// </summary>
None = 0,
/// <summary>
/// Replace: replace the file in the destination.
/// </summary>
Replace = 1,
/// <summary>
/// Skip: skip this file.
/// </summary>
Skip = 2,
/// <summary>
/// Rename: rename the file (like a window behavior)
/// </summary>
Rename = 3
}
/// <summary>
/// Rename the file.
/// </summary>
/// <param name="fileInfo">the target file.</param>
/// <param name="newFileName">new filename with extension.</param>
/// <param name="fileExistBehavior">behavior when new filename is exist.</param>
public static void Rename(this System.IO.FileInfo fileInfo, string newFileName, FileExistBehavior fileExistBehavior = FileExistBehavior.None)
{
string newFileNameWithoutExtension = System.IO.Path.GetFileNameWithoutExtension(newFileName);
string newFileNameExtension = System.IO.Path.GetExtension(newFileName);
string newFilePath = System.IO.Path.Combine(fileInfo.Directory.FullName, newFileName);
if (System.IO.File.Exists(newFilePath))
{
switch (fileExistBehavior)
{
case FileExistBehavior.None:
throw new System.IO.IOException("The destination file already exists.");
case FileExistBehavior.Replace:
System.IO.File.Delete(newFilePath);
break;
case FileExistBehavior.Rename:
int dupplicate_count = 0;
string newFileNameWithDupplicateIndex;
string newFilePathWithDupplicateIndex;
do
{
dupplicate_count++;
newFileNameWithDupplicateIndex = newFileNameWithoutExtension + " (" + dupplicate_count + ")" + newFileNameExtension;
newFilePathWithDupplicateIndex = System.IO.Path.Combine(fileInfo.Directory.FullName, newFileNameWithDupplicateIndex);
}
while (System.IO.File.Exists(newFilePathWithDupplicateIndex));
newFilePath = newFilePathWithDupplicateIndex;
break;
case FileExistBehavior.Skip:
return;
}
}
System.IO.File.Move(fileInfo.FullName, newFilePath);
}
}
How to use this code
class Program
{
static void Main(string[] args)
{
string targetFile = System.IO.Path.Combine(#"D://test", "New Text Document.txt");
string newFileName = "Foo.txt";
// Full pattern
System.IO.FileInfo fileInfo = new System.IO.FileInfo(targetFile);
fileInfo.Rename(newFileName);
// Or short form
new System.IO.FileInfo(targetFile).Rename(newFileName);
}
}
I couldn't find an approach which suits me, so I propose my version. Of course, it needs input and error handling.
public void Rename(string filePath, string newFileName)
{
var newFilePath = Path.Combine(Path.GetDirectoryName(filePath), newFileName + Path.GetExtension(filePath));
System.IO.File.Move(filePath, newFilePath);
}
In my case, I want the name of the renamed file to be unique, so I add a date-time stamp to the name. This way, the filename of the 'old' log is always unique:
if (File.Exists(clogfile))
{
Int64 fileSizeInBytes = new FileInfo(clogfile).Length;
if (fileSizeInBytes > 5000000)
{
string path = Path.GetFullPath(clogfile);
string filename = Path.GetFileNameWithoutExtension(clogfile);
System.IO.File.Move(clogfile, Path.Combine(path, string.Format("{0}{1}.log", filename, DateTime.Now.ToString("yyyyMMdd_HHmmss"))));
}
}
Move is doing the same = copy and delete old one.
File.Move(#"C:\ScanPDF\Test.pdf", #"C:\BackupPDF\" + string.Format("backup-{0:yyyy-MM-dd_HH:mm:ss}.pdf", DateTime.Now));
// Source file to be renamed
string sourceFile = #"C:\Temp\MaheshChand.jpg";
// Create a FileInfo
System.IO.FileInfo fi = new System.IO.FileInfo(sourceFile);
// Check if file is there
if (fi.Exists)
{
// Move file with a new name. Hence renamed.
fi.MoveTo(#"C:\Temp\Mahesh.jpg");
Console.WriteLine("File Renamed.");
}
public static class ImageRename
{
public static void ApplyChanges(string fileUrl,
string temporaryImageName,
string permanentImageName)
{
var currentFileName = Path.Combine(fileUrl,
temporaryImageName);
if (!File.Exists(currentFileName))
throw new FileNotFoundException();
var extention = Path.GetExtension(temporaryImageName);
var newFileName = Path.Combine(fileUrl,
$"{permanentImageName}
{extention}");
if (File.Exists(newFileName))
File.Delete(newFileName);
File.Move(currentFileName, newFileName);
}
}
I've encountered a case when I had to rename the file inside the event handler, which was triggering for any file change, including rename, and to skip forever renaming of the file I had to rename it, with:
Making its copy
Removing the original
File.Copy(fileFullPath, destFileName); // Both have the format of "D:\..\..\myFile.ext"
Thread.Sleep(100); // Wait for the OS to unfocus the file
File.Delete(fileFullPath);
private static void Rename_File(string FileFullPath, string NewName) // nes name without directory actualy you can simply rename with fileinfo.MoveTo(Fullpathwithnameandextension);
{
FileInfo fileInfo = new FileInfo(FileFullPath);
string DirectoryRoot = Directory.GetParent(FileFullPath).FullName;
string filecreator = FileFullPath.Substring(DirectoryRoot.Length,FileFullPath.Length-DirectoryRoot.Length);
filecreator = DirectoryRoot + NewName;
try
{
fileInfo.MoveTo(filecreator);
}
catch(Exception ex)
{
Console.WriteLine(filecreator);
Console.WriteLine(ex.Message);
Console.ReadKey();
}
enter code here
// string FileDirectory = Directory.GetDirectoryRoot()
}
When C# doesn't have some feature, I use C++ or C:
public partial class Program
{
[DllImport("msvcrt", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
public static extern int rename(
[MarshalAs(UnmanagedType.LPStr)]
string oldpath,
[MarshalAs(UnmanagedType.LPStr)]
string newpath);
static void FileRename()
{
while (true)
{
Console.Clear();
Console.Write("Enter a folder name: ");
string dir = Console.ReadLine().Trim('\\') + "\\";
if (string.IsNullOrWhiteSpace(dir))
break;
if (!Directory.Exists(dir))
{
Console.WriteLine("{0} does not exist", dir);
continue;
}
string[] files = Directory.GetFiles(dir, "*.mp3");
for (int i = 0; i < files.Length; i++)
{
string oldName = Path.GetFileName(files[i]);
int pos = oldName.IndexOfAny(new char[] { '0', '1', '2' });
if (pos == 0)
continue;
string newName = oldName.Substring(pos);
int res = rename(files[i], dir + newName);
}
}
Console.WriteLine("\n\t\tPress any key to go to main menu\n");
Console.ReadKey(true);
}
}

How to find list of files in "StreamingAssets" folder in Android

I have some files in my StreamingAssets folder and I am able to load them on Android as mentioned in the Unity documentation. https://docs.unity3d.com/ScriptReference/Application-streamingAssetsPath.html
But here I need to know the filename in advance.
Now I want to get list of all the files I have added in this directory. Following code does not work on Android. It gives directory not found exception.
DirectoryInfo dir = new DirectoryInfo(Application.streamingAssetsPath);
FileInfo[] info = dir.GetFiles("*.*");
So I want to know how do I get list of files in my StreamingAssets folder on Android. I need the file name so I can access the filename.
Use Better Streaming Assets, a free and open source plug in that parses APK/OBB archive to get the list of streaming assets. It also lets you read them without WWW.
Asset Store: https://www.assetstore.unity3d.com/#!/content/103788
Github: https://github.com/gwiazdorrr/BetterStreamingAssets
Hope this helps!
A simple way to solve this is to write the list of files in a .txt file before building the application and load the .txt file to access the file paths later in-game.
Add the BuildProcessor.cs script anywhere in your project, it will be executed each time you build the application.
#if UNITY_EDITOR
using System.Collections.Generic;
using System.IO;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using UnityEngine;
class BuildProcessor : IPreprocessBuildWithReport
{
public int callbackOrder { get { return 0; } }
public void OnPreprocessBuild(BuildReport report)
{
Debug.LogWarning("OnPreprocessBuild");
SaveStreamingAssetPaths();
}
private void SaveStreamingAssetPaths(string directory = "", string file_name = "StreamingAssetPaths")
{
List<string> paths = StreamingAssetsExtension.GetPathsRecursively(directory); // Gets list of files from StreamingAssets/directory
// You could also save paths of files in Resources
// List<string> paths = ResourcesExtension.GetPathsRecursively(directory); // Gets list of files from Resources/directory
string txtPath = Path.Combine(Application.dataPath, "Resources", file_name + ".txt"); // writes the list of file paths to /Assets/Resources/
if (File.Exists(txtPath))
{
File.Delete(txtPath);
}
using (FileStream fs = File.Create(txtPath)) {}
using(StreamWriter writer = new StreamWriter(txtPath, false))
{
foreach (string path in paths)
{
writer.WriteLine(path);
}
}
}
}
#endif
It uses the following extension methods:
For files in StreamingAssets, use StreamingAssetsExtension.cs:
using System.Collections.Generic;
using System.IO;
using UnityEngine;
public static class StreamingAssetsExtension
{
/// <summary>
/// Recursively traverses each folder under <paramref name="path"/> and returns the list of file paths.
/// It will only work in Editor mode.
/// </summary>
/// <param name="path">Relative to Application.streamingAssetsPath.</param>
/// <param name="paths">List of file path strings.</param>
/// <returns>List of file path strings.</returns>
public static List<string> GetPathsRecursively(string path, ref List<string> paths)
{
var fullPath = Path.Combine(Application.streamingAssetsPath, path);
DirectoryInfo dirInfo = new DirectoryInfo(fullPath);
foreach (var file in dirInfo.GetFiles())
{
if (!file.Name.Contains(".meta"))
{
paths.Add(Path.Combine(path, file.Name)); // With file extension
}
}
foreach (var dir in dirInfo.GetDirectories())
{
GetPathsRecursively(Path.Combine(path, dir.Name), ref paths);
}
return paths;
}
public static List<string> GetPathsRecursively(string path)
{
List<string> paths = new List<string>();
return GetPathsRecursively(path, ref paths);
}
}
For files in Resources, use ResourcesExtension.cs:
using System.Collections.Generic;
using System.IO;
using UnityEngine;
public static class ResourcesExtension
{
/// <summary>
/// Recursively traverses each folder under <paramref name="path"/> and returns the list of file paths.
/// It will only work in Editor mode.
/// </summary>
/// <param name="path">Relative to Application.streamingAssetsPath.</param>
/// <param name="paths">List of file path strings.</param>
/// <returns>List of file path strings.</returns>
public static List<string> GetPathsRecursively(string path, ref List<string> paths)
{
var fullPath = Path.Combine(Application.dataPath, "Resources", path);
DirectoryInfo dirInfo = new DirectoryInfo(fullPath);
foreach (var file in dirInfo.GetFiles())
{
if (!file.Name.Contains(".meta"))
{
paths.Add(Path.Combine(path, Path.GetFileNameWithoutExtension(file.Name))); // Without file extension
}
}
foreach (var dir in dirInfo.GetDirectories())
{
GetPathsRecursively(Path.Combine(path, dir.Name), ref paths);
}
return paths;
}
public static List<string> GetPathsRecursively(string path)
{
List<string> paths = new List<string>();
return GetPathsRecursively(path, ref paths);
}
/// <summary>
/// Recursively traverses each folder under <paramref name="basePath"/> and loads each file as a <typeparamref name="T"/>.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="basePath"></param>
/// <returns>Returns the loaded object of type <typeparamref name="T"/></returns>
public static List<T> LoadRecursively<T>(string basePath) where T : Object
{
List<string> paths = GetPathsRecursively(basePath);
List<T> objects = new List<T>();
foreach (var path in paths)
{
objects.Add(Resources.Load<T>(path));
}
return objects;
}
public static List<(T, string)> LoadRecursivelyWithPaths<T>(string basePath) where T : Object
{
List<string> paths = new List<string>();
GetPathsRecursively(basePath, ref paths);
List<(T, string)> list = new List<(T, string)>();
foreach (var path in paths)
{
list.Add((Resources.Load<T>(path), path));
}
return list;
}
}
You can retrieve the file paths as the following:
// ...
List<string> filePathsList = new List<string>();
TextAsset paths = Resources.Load<TextAsset>(file_name); // i.e. StreamingAssetPaths.txt
string fs = paths.text;
string[] fLines = Regex.Split(fs, "\n|\r|\r\n");
foreach (string line in fLines)
{
if (line.Length > 0)
filePathsList.Add(line);
}
// ...
// Example of loading:
string examplePath = filePathsList[0];
// If the file is in StreamingAssets:
...
path = Path.Combine(Application.streamingAssetsPath, examplePath);
byte[] data = null;
int dataLen = 0;
UnityWebRequest webRequest = UnityWebRequest.Get(path);
yield return webRequest.SendWebRequest();
if (webRequest.result == UnityWebRequest.Result.Success)
{
dataLen = webRequest.downloadHandler.data.Length;
data = webRequest.downloadHandler.data;
}
// do whatever you want with the data ...
// If the file is in Resources:
...
ObjectType obj = Resources.Load<ObjectType>(examplePath);
...
I think this question is already been answered....
http://answers.unity3d.com/questions/210909/android-streamingassets-file-access.html

Sharepoint uploaded file name was changed by server event. How to retrieve it?

I'm uploading file to Sharepoint server using this code:
ClientOM.File uploadFile = null;
try {
string fileRef = serverRelativeURL + msg.Message.FileName;
FileCreationInformation fileCreationInformation = new FileCreationInformation() {
Content = msg.Content,
Url = fileRef,
Overwrite = true
};
uploadFile = _currentList.RootFolder.Files.Add(fileCreationInformation);
_currentContext.ExecuteQuery();
And file uploaded. But on server we have event that adds some random string to the file title. So fileRef is not relevant after upload.
And we need to set the Author of the file. For this we have to retrieve file and update this propery. I do it with this sample:
string fileName = serverRelativeURL + msg.Message.FileName;
uploadFile = _currentContext.Web.GetFileByServerRelativeUrl(fileName);
_currentContext.Load(uploadFile);
uploadFile.ListItemAllFields["Author"] = _currentUser;
uploadFile.ListItemAllFields["Editor"] = _currentUser;
uploadFile.ListItemAllFields.Update();
_currentContext.ExecuteQuery();
And on ExecuteQuery() I get an Exception "File not found". But if I copy path from Sharepoint (with that random string) everything works Ok.
So the question is: Is there other way to retrieve file? By id for example? because when we uploading file, instance "uploadFile" does not have much of useful information.
Method 1:
Keep track of the filename, and then use this code to retrieve it directly.
public FileInformation GetFileFromAttachment(int itemId, string filename)
{
FileInformation file = null;
//continue here
if (new FileInfo(filename).Name != null)
{
CSOMUtils.ExecuteInNewContext(QueryConfig.siteUrl, delegate(ClientContext clientContext)
{
clientContext.Credentials = QueryConfig.credentials;
clientContext.Load(clientContext.Web, l => l.ServerRelativeUrl);
clientContext.ExecuteQuery();
List oList = clientContext.Web.Lists.GetByTitle(ListName);
clientContext.ExecuteQuery();
string url = string.Format("{0}/Lists/{1}/Attachments/{2}/{3}",
clientContext.Web.ServerRelativeUrl,
ListName,
itemId,
filename);
var f = clientContext.Web.GetFileByServerRelativeUrl(url);
clientContext.Load(f);
clientContext.ExecuteQuery();
file = File.OpenBinaryDirect(clientContext, f.ServerRelativeUrl);
});
}
return file;
}
Method 2:
You can use ServerRelativeUrl to get the folder containing all the attachments.
https://msdn.microsoft.com/library/office/microsoft.sharepoint.client.folder.serverrelativeurl.aspx
https://sharepoint.stackexchange.com/questions/132008/reliably-get-attachments-for-list-item

Renaming Pinned Application [duplicate]

How do I rename a file using C#?
Take a look at System.IO.File.Move, "move" the file to a new name.
System.IO.File.Move("oldfilename", "newfilename");
System.IO.File.Move(oldNameFullPath, newNameFullPath);
In the File.Move method, this won't overwrite the file if it is already exists. And it will throw an exception.
So we need to check whether the file exists or not.
/* Delete the file if exists, else no exception thrown. */
File.Delete(newFileName); // Delete the existing file if exists
File.Move(oldFileName,newFileName); // Rename the oldFileName into newFileName
Or surround it with a try catch to avoid an exception.
Just add:
namespace System.IO
{
public static class ExtendedMethod
{
public static void Rename(this FileInfo fileInfo, string newName)
{
fileInfo.MoveTo(fileInfo.Directory.FullName + "\\" + newName);
}
}
}
And then...
FileInfo file = new FileInfo("c:\test.txt");
file.Rename("test2.txt");
You can use File.Move to do it.
First solution
Avoid System.IO.File.Move solutions posted here (marked answer included).
It fails over networks. However, copy/delete pattern works locally and over networks. Follow one of the move solutions, but replace it with Copy instead. Then use File.Delete to delete the original file.
You can create a Rename method to simplify it.
Ease of use
Use the VB assembly in C#.
Add reference to Microsoft.VisualBasic
Then to rename the file:
Microsoft.VisualBasic.FileIO.FileSystem.RenameFile(myfile, newName);
Both are strings. Note that myfile has the full path. newName does not.
For example:
a = "C:\whatever\a.txt";
b = "b.txt";
Microsoft.VisualBasic.FileIO.FileSystem.RenameFile(a, b);
The C:\whatever\ folder will now contain b.txt.
You can copy it as a new file and then delete the old one using the System.IO.File class:
if (File.Exists(oldName))
{
File.Copy(oldName, newName, true);
File.Delete(oldName);
}
public void RenameFile(string filePath, string newName)
{
FileInfo fileInfo = new FileInfo(filePath);
fileInfo.MoveTo(fileInfo.Directory.FullName + "\\" + newName);
}
NOTE: In this example code we open a directory and search for PDF files with open and closed parenthesis in the name of the file. You can check and replace any character in the name you like or just specify a whole new name using replace functions.
There are other ways to work from this code to do more elaborate renames but my main intention was to show how to use File.Move to do a batch rename. This worked against 335 PDF files in 180 directories when I ran it on my laptop. This is spur of the moment code and there are more elaborate ways to do it.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BatchRenamer
{
class Program
{
static void Main(string[] args)
{
var dirnames = Directory.GetDirectories(#"C:\the full directory path of files to rename goes here");
int i = 0;
try
{
foreach (var dir in dirnames)
{
var fnames = Directory.GetFiles(dir, "*.pdf").Select(Path.GetFileName);
DirectoryInfo d = new DirectoryInfo(dir);
FileInfo[] finfo = d.GetFiles("*.pdf");
foreach (var f in fnames)
{
i++;
Console.WriteLine("The number of the file being renamed is: {0}", i);
if (!File.Exists(Path.Combine(dir, f.ToString().Replace("(", "").Replace(")", ""))))
{
File.Move(Path.Combine(dir, f), Path.Combine(dir, f.ToString().Replace("(", "").Replace(")", "")));
}
else
{
Console.WriteLine("The file you are attempting to rename already exists! The file path is {0}.", dir);
foreach (FileInfo fi in finfo)
{
Console.WriteLine("The file modify date is: {0} ", File.GetLastWriteTime(dir));
}
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.Read();
}
}
}
None of the answers mention writing a unit testable solution. You could use System.IO.Abstractions as it provides a testable wrapper around FileSystem operations, using which you can create a mocked file system objects and write unit tests.
using System.IO.Abstractions;
IFileInfo fileInfo = _fileSystem.FileInfo.FromFileName("filePathAndName");
fileInfo.MoveTo(Path.Combine(fileInfo.DirectoryName, newName));
It was tested, and it is working code to rename a file.
Use:
using System.IO;
string oldFilePath = #"C:\OldFile.txt"; // Full path of old file
string newFilePath = #"C:\NewFile.txt"; // Full path of new file
if (File.Exists(newFilePath))
{
File.Delete(newFilePath);
}
File.Move(oldFilePath, newFilePath);
Use:
public static class FileInfoExtensions
{
/// <summary>
/// Behavior when a new filename exists.
/// </summary>
public enum FileExistBehavior
{
/// <summary>
/// None: throw IOException "The destination file already exists."
/// </summary>
None = 0,
/// <summary>
/// Replace: replace the file in the destination.
/// </summary>
Replace = 1,
/// <summary>
/// Skip: skip this file.
/// </summary>
Skip = 2,
/// <summary>
/// Rename: rename the file (like a window behavior)
/// </summary>
Rename = 3
}
/// <summary>
/// Rename the file.
/// </summary>
/// <param name="fileInfo">the target file.</param>
/// <param name="newFileName">new filename with extension.</param>
/// <param name="fileExistBehavior">behavior when new filename is exist.</param>
public static void Rename(this System.IO.FileInfo fileInfo, string newFileName, FileExistBehavior fileExistBehavior = FileExistBehavior.None)
{
string newFileNameWithoutExtension = System.IO.Path.GetFileNameWithoutExtension(newFileName);
string newFileNameExtension = System.IO.Path.GetExtension(newFileName);
string newFilePath = System.IO.Path.Combine(fileInfo.Directory.FullName, newFileName);
if (System.IO.File.Exists(newFilePath))
{
switch (fileExistBehavior)
{
case FileExistBehavior.None:
throw new System.IO.IOException("The destination file already exists.");
case FileExistBehavior.Replace:
System.IO.File.Delete(newFilePath);
break;
case FileExistBehavior.Rename:
int dupplicate_count = 0;
string newFileNameWithDupplicateIndex;
string newFilePathWithDupplicateIndex;
do
{
dupplicate_count++;
newFileNameWithDupplicateIndex = newFileNameWithoutExtension + " (" + dupplicate_count + ")" + newFileNameExtension;
newFilePathWithDupplicateIndex = System.IO.Path.Combine(fileInfo.Directory.FullName, newFileNameWithDupplicateIndex);
}
while (System.IO.File.Exists(newFilePathWithDupplicateIndex));
newFilePath = newFilePathWithDupplicateIndex;
break;
case FileExistBehavior.Skip:
return;
}
}
System.IO.File.Move(fileInfo.FullName, newFilePath);
}
}
How to use this code
class Program
{
static void Main(string[] args)
{
string targetFile = System.IO.Path.Combine(#"D://test", "New Text Document.txt");
string newFileName = "Foo.txt";
// Full pattern
System.IO.FileInfo fileInfo = new System.IO.FileInfo(targetFile);
fileInfo.Rename(newFileName);
// Or short form
new System.IO.FileInfo(targetFile).Rename(newFileName);
}
}
I couldn't find an approach which suits me, so I propose my version. Of course, it needs input and error handling.
public void Rename(string filePath, string newFileName)
{
var newFilePath = Path.Combine(Path.GetDirectoryName(filePath), newFileName + Path.GetExtension(filePath));
System.IO.File.Move(filePath, newFilePath);
}
In my case, I want the name of the renamed file to be unique, so I add a date-time stamp to the name. This way, the filename of the 'old' log is always unique:
if (File.Exists(clogfile))
{
Int64 fileSizeInBytes = new FileInfo(clogfile).Length;
if (fileSizeInBytes > 5000000)
{
string path = Path.GetFullPath(clogfile);
string filename = Path.GetFileNameWithoutExtension(clogfile);
System.IO.File.Move(clogfile, Path.Combine(path, string.Format("{0}{1}.log", filename, DateTime.Now.ToString("yyyyMMdd_HHmmss"))));
}
}
Move is doing the same = copy and delete old one.
File.Move(#"C:\ScanPDF\Test.pdf", #"C:\BackupPDF\" + string.Format("backup-{0:yyyy-MM-dd_HH:mm:ss}.pdf", DateTime.Now));
// Source file to be renamed
string sourceFile = #"C:\Temp\MaheshChand.jpg";
// Create a FileInfo
System.IO.FileInfo fi = new System.IO.FileInfo(sourceFile);
// Check if file is there
if (fi.Exists)
{
// Move file with a new name. Hence renamed.
fi.MoveTo(#"C:\Temp\Mahesh.jpg");
Console.WriteLine("File Renamed.");
}
public static class ImageRename
{
public static void ApplyChanges(string fileUrl,
string temporaryImageName,
string permanentImageName)
{
var currentFileName = Path.Combine(fileUrl,
temporaryImageName);
if (!File.Exists(currentFileName))
throw new FileNotFoundException();
var extention = Path.GetExtension(temporaryImageName);
var newFileName = Path.Combine(fileUrl,
$"{permanentImageName}
{extention}");
if (File.Exists(newFileName))
File.Delete(newFileName);
File.Move(currentFileName, newFileName);
}
}
I've encountered a case when I had to rename the file inside the event handler, which was triggering for any file change, including rename, and to skip forever renaming of the file I had to rename it, with:
Making its copy
Removing the original
File.Copy(fileFullPath, destFileName); // Both have the format of "D:\..\..\myFile.ext"
Thread.Sleep(100); // Wait for the OS to unfocus the file
File.Delete(fileFullPath);
private static void Rename_File(string FileFullPath, string NewName) // nes name without directory actualy you can simply rename with fileinfo.MoveTo(Fullpathwithnameandextension);
{
FileInfo fileInfo = new FileInfo(FileFullPath);
string DirectoryRoot = Directory.GetParent(FileFullPath).FullName;
string filecreator = FileFullPath.Substring(DirectoryRoot.Length,FileFullPath.Length-DirectoryRoot.Length);
filecreator = DirectoryRoot + NewName;
try
{
fileInfo.MoveTo(filecreator);
}
catch(Exception ex)
{
Console.WriteLine(filecreator);
Console.WriteLine(ex.Message);
Console.ReadKey();
}
enter code here
// string FileDirectory = Directory.GetDirectoryRoot()
}
When C# doesn't have some feature, I use C++ or C:
public partial class Program
{
[DllImport("msvcrt", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
public static extern int rename(
[MarshalAs(UnmanagedType.LPStr)]
string oldpath,
[MarshalAs(UnmanagedType.LPStr)]
string newpath);
static void FileRename()
{
while (true)
{
Console.Clear();
Console.Write("Enter a folder name: ");
string dir = Console.ReadLine().Trim('\\') + "\\";
if (string.IsNullOrWhiteSpace(dir))
break;
if (!Directory.Exists(dir))
{
Console.WriteLine("{0} does not exist", dir);
continue;
}
string[] files = Directory.GetFiles(dir, "*.mp3");
for (int i = 0; i < files.Length; i++)
{
string oldName = Path.GetFileName(files[i]);
int pos = oldName.IndexOfAny(new char[] { '0', '1', '2' });
if (pos == 0)
continue;
string newName = oldName.Substring(pos);
int res = rename(files[i], dir + newName);
}
}
Console.WriteLine("\n\t\tPress any key to go to main menu\n");
Console.ReadKey(true);
}
}

Rename a file in C#

How do I rename a file using C#?
Take a look at System.IO.File.Move, "move" the file to a new name.
System.IO.File.Move("oldfilename", "newfilename");
System.IO.File.Move(oldNameFullPath, newNameFullPath);
In the File.Move method, this won't overwrite the file if it is already exists. And it will throw an exception.
So we need to check whether the file exists or not.
/* Delete the file if exists, else no exception thrown. */
File.Delete(newFileName); // Delete the existing file if exists
File.Move(oldFileName,newFileName); // Rename the oldFileName into newFileName
Or surround it with a try catch to avoid an exception.
Just add:
namespace System.IO
{
public static class ExtendedMethod
{
public static void Rename(this FileInfo fileInfo, string newName)
{
fileInfo.MoveTo(fileInfo.Directory.FullName + "\\" + newName);
}
}
}
And then...
FileInfo file = new FileInfo("c:\test.txt");
file.Rename("test2.txt");
You can use File.Move to do it.
First solution
Avoid System.IO.File.Move solutions posted here (marked answer included).
It fails over networks. However, copy/delete pattern works locally and over networks. Follow one of the move solutions, but replace it with Copy instead. Then use File.Delete to delete the original file.
You can create a Rename method to simplify it.
Ease of use
Use the VB assembly in C#.
Add reference to Microsoft.VisualBasic
Then to rename the file:
Microsoft.VisualBasic.FileIO.FileSystem.RenameFile(myfile, newName);
Both are strings. Note that myfile has the full path. newName does not.
For example:
a = "C:\whatever\a.txt";
b = "b.txt";
Microsoft.VisualBasic.FileIO.FileSystem.RenameFile(a, b);
The C:\whatever\ folder will now contain b.txt.
You can copy it as a new file and then delete the old one using the System.IO.File class:
if (File.Exists(oldName))
{
File.Copy(oldName, newName, true);
File.Delete(oldName);
}
public void RenameFile(string filePath, string newName)
{
FileInfo fileInfo = new FileInfo(filePath);
fileInfo.MoveTo(fileInfo.Directory.FullName + "\\" + newName);
}
NOTE: In this example code we open a directory and search for PDF files with open and closed parenthesis in the name of the file. You can check and replace any character in the name you like or just specify a whole new name using replace functions.
There are other ways to work from this code to do more elaborate renames but my main intention was to show how to use File.Move to do a batch rename. This worked against 335 PDF files in 180 directories when I ran it on my laptop. This is spur of the moment code and there are more elaborate ways to do it.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BatchRenamer
{
class Program
{
static void Main(string[] args)
{
var dirnames = Directory.GetDirectories(#"C:\the full directory path of files to rename goes here");
int i = 0;
try
{
foreach (var dir in dirnames)
{
var fnames = Directory.GetFiles(dir, "*.pdf").Select(Path.GetFileName);
DirectoryInfo d = new DirectoryInfo(dir);
FileInfo[] finfo = d.GetFiles("*.pdf");
foreach (var f in fnames)
{
i++;
Console.WriteLine("The number of the file being renamed is: {0}", i);
if (!File.Exists(Path.Combine(dir, f.ToString().Replace("(", "").Replace(")", ""))))
{
File.Move(Path.Combine(dir, f), Path.Combine(dir, f.ToString().Replace("(", "").Replace(")", "")));
}
else
{
Console.WriteLine("The file you are attempting to rename already exists! The file path is {0}.", dir);
foreach (FileInfo fi in finfo)
{
Console.WriteLine("The file modify date is: {0} ", File.GetLastWriteTime(dir));
}
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.Read();
}
}
}
None of the answers mention writing a unit testable solution. You could use System.IO.Abstractions as it provides a testable wrapper around FileSystem operations, using which you can create a mocked file system objects and write unit tests.
using System.IO.Abstractions;
IFileInfo fileInfo = _fileSystem.FileInfo.FromFileName("filePathAndName");
fileInfo.MoveTo(Path.Combine(fileInfo.DirectoryName, newName));
It was tested, and it is working code to rename a file.
Use:
using System.IO;
string oldFilePath = #"C:\OldFile.txt"; // Full path of old file
string newFilePath = #"C:\NewFile.txt"; // Full path of new file
if (File.Exists(newFilePath))
{
File.Delete(newFilePath);
}
File.Move(oldFilePath, newFilePath);
Use:
public static class FileInfoExtensions
{
/// <summary>
/// Behavior when a new filename exists.
/// </summary>
public enum FileExistBehavior
{
/// <summary>
/// None: throw IOException "The destination file already exists."
/// </summary>
None = 0,
/// <summary>
/// Replace: replace the file in the destination.
/// </summary>
Replace = 1,
/// <summary>
/// Skip: skip this file.
/// </summary>
Skip = 2,
/// <summary>
/// Rename: rename the file (like a window behavior)
/// </summary>
Rename = 3
}
/// <summary>
/// Rename the file.
/// </summary>
/// <param name="fileInfo">the target file.</param>
/// <param name="newFileName">new filename with extension.</param>
/// <param name="fileExistBehavior">behavior when new filename is exist.</param>
public static void Rename(this System.IO.FileInfo fileInfo, string newFileName, FileExistBehavior fileExistBehavior = FileExistBehavior.None)
{
string newFileNameWithoutExtension = System.IO.Path.GetFileNameWithoutExtension(newFileName);
string newFileNameExtension = System.IO.Path.GetExtension(newFileName);
string newFilePath = System.IO.Path.Combine(fileInfo.Directory.FullName, newFileName);
if (System.IO.File.Exists(newFilePath))
{
switch (fileExistBehavior)
{
case FileExistBehavior.None:
throw new System.IO.IOException("The destination file already exists.");
case FileExistBehavior.Replace:
System.IO.File.Delete(newFilePath);
break;
case FileExistBehavior.Rename:
int dupplicate_count = 0;
string newFileNameWithDupplicateIndex;
string newFilePathWithDupplicateIndex;
do
{
dupplicate_count++;
newFileNameWithDupplicateIndex = newFileNameWithoutExtension + " (" + dupplicate_count + ")" + newFileNameExtension;
newFilePathWithDupplicateIndex = System.IO.Path.Combine(fileInfo.Directory.FullName, newFileNameWithDupplicateIndex);
}
while (System.IO.File.Exists(newFilePathWithDupplicateIndex));
newFilePath = newFilePathWithDupplicateIndex;
break;
case FileExistBehavior.Skip:
return;
}
}
System.IO.File.Move(fileInfo.FullName, newFilePath);
}
}
How to use this code
class Program
{
static void Main(string[] args)
{
string targetFile = System.IO.Path.Combine(#"D://test", "New Text Document.txt");
string newFileName = "Foo.txt";
// Full pattern
System.IO.FileInfo fileInfo = new System.IO.FileInfo(targetFile);
fileInfo.Rename(newFileName);
// Or short form
new System.IO.FileInfo(targetFile).Rename(newFileName);
}
}
I couldn't find an approach which suits me, so I propose my version. Of course, it needs input and error handling.
public void Rename(string filePath, string newFileName)
{
var newFilePath = Path.Combine(Path.GetDirectoryName(filePath), newFileName + Path.GetExtension(filePath));
System.IO.File.Move(filePath, newFilePath);
}
In my case, I want the name of the renamed file to be unique, so I add a date-time stamp to the name. This way, the filename of the 'old' log is always unique:
if (File.Exists(clogfile))
{
Int64 fileSizeInBytes = new FileInfo(clogfile).Length;
if (fileSizeInBytes > 5000000)
{
string path = Path.GetFullPath(clogfile);
string filename = Path.GetFileNameWithoutExtension(clogfile);
System.IO.File.Move(clogfile, Path.Combine(path, string.Format("{0}{1}.log", filename, DateTime.Now.ToString("yyyyMMdd_HHmmss"))));
}
}
Move is doing the same = copy and delete old one.
File.Move(#"C:\ScanPDF\Test.pdf", #"C:\BackupPDF\" + string.Format("backup-{0:yyyy-MM-dd_HH:mm:ss}.pdf", DateTime.Now));
// Source file to be renamed
string sourceFile = #"C:\Temp\MaheshChand.jpg";
// Create a FileInfo
System.IO.FileInfo fi = new System.IO.FileInfo(sourceFile);
// Check if file is there
if (fi.Exists)
{
// Move file with a new name. Hence renamed.
fi.MoveTo(#"C:\Temp\Mahesh.jpg");
Console.WriteLine("File Renamed.");
}
public static class ImageRename
{
public static void ApplyChanges(string fileUrl,
string temporaryImageName,
string permanentImageName)
{
var currentFileName = Path.Combine(fileUrl,
temporaryImageName);
if (!File.Exists(currentFileName))
throw new FileNotFoundException();
var extention = Path.GetExtension(temporaryImageName);
var newFileName = Path.Combine(fileUrl,
$"{permanentImageName}
{extention}");
if (File.Exists(newFileName))
File.Delete(newFileName);
File.Move(currentFileName, newFileName);
}
}
I've encountered a case when I had to rename the file inside the event handler, which was triggering for any file change, including rename, and to skip forever renaming of the file I had to rename it, with:
Making its copy
Removing the original
File.Copy(fileFullPath, destFileName); // Both have the format of "D:\..\..\myFile.ext"
Thread.Sleep(100); // Wait for the OS to unfocus the file
File.Delete(fileFullPath);
private static void Rename_File(string FileFullPath, string NewName) // nes name without directory actualy you can simply rename with fileinfo.MoveTo(Fullpathwithnameandextension);
{
FileInfo fileInfo = new FileInfo(FileFullPath);
string DirectoryRoot = Directory.GetParent(FileFullPath).FullName;
string filecreator = FileFullPath.Substring(DirectoryRoot.Length,FileFullPath.Length-DirectoryRoot.Length);
filecreator = DirectoryRoot + NewName;
try
{
fileInfo.MoveTo(filecreator);
}
catch(Exception ex)
{
Console.WriteLine(filecreator);
Console.WriteLine(ex.Message);
Console.ReadKey();
}
enter code here
// string FileDirectory = Directory.GetDirectoryRoot()
}
When C# doesn't have some feature, I use C++ or C:
public partial class Program
{
[DllImport("msvcrt", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
public static extern int rename(
[MarshalAs(UnmanagedType.LPStr)]
string oldpath,
[MarshalAs(UnmanagedType.LPStr)]
string newpath);
static void FileRename()
{
while (true)
{
Console.Clear();
Console.Write("Enter a folder name: ");
string dir = Console.ReadLine().Trim('\\') + "\\";
if (string.IsNullOrWhiteSpace(dir))
break;
if (!Directory.Exists(dir))
{
Console.WriteLine("{0} does not exist", dir);
continue;
}
string[] files = Directory.GetFiles(dir, "*.mp3");
for (int i = 0; i < files.Length; i++)
{
string oldName = Path.GetFileName(files[i]);
int pos = oldName.IndexOfAny(new char[] { '0', '1', '2' });
if (pos == 0)
continue;
string newName = oldName.Substring(pos);
int res = rename(files[i], dir + newName);
}
}
Console.WriteLine("\n\t\tPress any key to go to main menu\n");
Console.ReadKey(true);
}
}

Categories