forked from pnp/powershell
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathConvertFile.cs
152 lines (127 loc) · 6.72 KB
/
ConvertFile.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
using Microsoft.SharePoint.Client;
using PnP.Core.Model.SharePoint;
using PnP.Framework.Utilities;
using PnP.PowerShell.Commands.Base.PipeBinds;
using System.IO;
using System.Management.Automation;
namespace PnP.PowerShell.Commands.Files
{
[Cmdlet(VerbsData.Convert, "PnPFile")]
public class ConvertFile : PnPWebCmdlet
{
private const string URLTOPATH = "Save to local path";
private const string URLASMEMORYSTREAM = "Return as memorystream";
private const string UPLOADTOSHAREPOINT = "Upload to SharePoint";
[Parameter(Mandatory = true, ParameterSetName = URLTOPATH, Position = 0, ValueFromPipeline = true)]
[Parameter(Mandatory = true, ParameterSetName = URLASMEMORYSTREAM, Position = 0, ValueFromPipeline = true)]
[Parameter(Mandatory = true, ParameterSetName = UPLOADTOSHAREPOINT, Position = 0, ValueFromPipeline = true)]
[Alias("ServerRelativeUrl", "SiteRelativeUrl")]
public string Url;
[Parameter(Mandatory = false, ParameterSetName = URLTOPATH)]
[Parameter(Mandatory = false, ParameterSetName = URLASMEMORYSTREAM)]
[Parameter(Mandatory = false, ParameterSetName = UPLOADTOSHAREPOINT)]
public ConvertToFormat ConvertToFormat = ConvertToFormat.Pdf;
[Parameter(Mandatory = true, ParameterSetName = URLTOPATH)]
public string Path = string.Empty;
[Parameter(Mandatory = false, ParameterSetName = URLTOPATH)]
[Parameter(Mandatory = false, ParameterSetName = UPLOADTOSHAREPOINT)]
public SwitchParameter Force;
[Parameter(Mandatory = true, ParameterSetName = UPLOADTOSHAREPOINT)]
[ValidateNotNullOrEmpty]
public FolderPipeBind Folder;
[Parameter(Mandatory = false, ParameterSetName = URLASMEMORYSTREAM)]
public SwitchParameter AsMemoryStream;
protected override void ExecuteCmdlet()
{
if (string.IsNullOrEmpty(Path))
{
Path = SessionState.Path.CurrentFileSystemLocation.Path;
}
else if (!System.IO.Path.IsPathRooted(Path))
{
Path = System.IO.Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path, Path);
}
// Remove URL decoding from the Url as that will not work. We will encode the + character specifically, because if that is part of the filename, it needs to stay and not be decoded.
Url = Utilities.UrlUtilities.UrlDecode(Url.Replace("+", "%2B"));
var webUrl = CurrentWeb.EnsureProperty(w => w.ServerRelativeUrl);
var serverRelativeUrl = string.Empty;
if (!Url.ToLower().StartsWith(webUrl.ToLower()))
{
serverRelativeUrl = UrlUtility.Combine(webUrl, Url);
}
else
{
serverRelativeUrl = Url;
}
IFile sourceFile = Connection.PnPContext.Web.GetFileByServerRelativeUrl(serverRelativeUrl, p => p.VroomDriveID, p => p.VroomItemID);
LogDebug("Converting file to the specified format");
var convertedFile = sourceFile.ConvertTo(new ConvertToOptions { Format = ConvertToFormat });
var fileName = System.IO.Path.GetFileNameWithoutExtension(sourceFile.Name);
var newFileName = fileName + "." + ConvertToFormat.ToString();
switch (ParameterSetName)
{
case URLTOPATH:
var fileOut = System.IO.Path.Combine(Path, newFileName);
if (System.IO.File.Exists(fileOut) && !Force)
{
LogWarning($"File '{sourceFile.Name}' exists already. Use the -Force parameter to overwrite the file.");
}
else
{
LogDebug("Saving file to the disc.");
using FileStream fs = new(fileOut, FileMode.Create);
convertedFile.CopyTo(fs);
}
break;
case URLASMEMORYSTREAM:
var stream = new MemoryStream();
convertedFile.CopyTo(stream);
WriteObject(stream);
break;
case UPLOADTOSHAREPOINT:
LogDebug("Uploading file to the specified folder");
var folder = EnsureFolder();
var uploadedFile = folder.UploadFile(newFileName, convertedFile, Force);
try
{
ClientContext.Load(uploadedFile, f => f.Author, f => f.Length, f => f.ModifiedBy, f => f.Name, f => f.TimeCreated, f => f.TimeLastModified, f => f.Title);
ClientContext.ExecuteQueryRetry();
}
catch (ServerException)
{
// Assume the cause of the exception is that a principal cannot be found and try again without:
// Fallback in case the creator or person having last modified the file no longer exists in the environment such that the file can still be downloaded
ClientContext.Load(uploadedFile, f => f.Length, f => f.Name, f => f.TimeCreated, f => f.TimeLastModified, f => f.Title);
ClientContext.ExecuteQueryRetry();
}
WriteObject(uploadedFile);
LogDebug("File uploaded.");
break;
}
}
/// <summary>
/// Ensures the folder to which the file is to be uploaded exists. Changed from using the EnsureFolder implementation in PnP Framework as that requires at least member rights to the entire site to work.
/// </summary>
/// <returns>The folder to which the file needs to be uploaded</returns>
private Folder EnsureFolder()
{
// First try to get the folder if it exists already. This avoids an Access Denied exception if the current user doesn't have Full Control access at Web level
CurrentWeb.EnsureProperty(w => w.ServerRelativeUrl);
Folder folder = null;
try
{
folder = Folder.GetFolder(CurrentWeb);
folder.EnsureProperties(f => f.ServerRelativeUrl);
return folder;
}
// Exception will be thrown if the folder does not exist yet on SharePoint
catch (ServerException serverEx) when (serverEx.ServerErrorCode == -2147024894)
{
// Try to create the folder
folder = CurrentWeb.EnsureFolder(CurrentWeb.RootFolder, Folder.ServerRelativeUrl);
folder.EnsureProperties(f => f.ServerRelativeUrl);
return folder;
}
}
}
}