Unterstützen von % und # in Dateien und Ordnern mit der ResourcePath-API
In SharePoint Online wird Unterstützung für % und # in Dateien und Ordnern bereitgestellt. Leider ist die Arbeit mit diesen Dateinamen aufgrund bestehender API-Strukturen und Aufrufmuster manchmal nicht eindeutig. Sie finden weitere Hintergründe hierzu in unserem Entwicklerblog.
Zusammenfassend lässt sich sagen, dass der Oberfläche des SharePoint Online-Clientobjektmodells (CSOM) neue APIs hinzugefügt wurden, um die Zeichen # und % zu unterstützen.
Neue ResourcePath-Klasse
Zusammenfassend ist zu beachten, dass bestehende zeichenfolgenbasierte SharePoint-APIs (wie SPFileCollection.GetByUrl) sowohl codierte als auch decodierte URLs verarbeiten, indem sie automatisch davon ausgehen, dass %- und #-Zeichen in einem Pfad bedeuten, dass die URL codiert wurde. Wegen der neuen Unterstützung für % und # in Dateien und Ordnern ist diese automatische Behandlung jetzt problematisch, da sie dazu führen kann, dass Dateinamen, die % und # enthalten, in Downstreamcode ignoriert oder falsch behandelt werden.
APIs wurde eine neue Klasse hinzugefügt: Microsoft.SharePoint.Client.ResourcePath
. Die ResourcePath-Klasse ist Voraussetzung für die Unterstützung dieser neuen Zeichen. Sie bietet eine neue, eindeutige Möglichkeit, ein Element in SharePoint und OneDrive for Business zu adressieren, weil sie von decodierten URLs ausgeht und nur mit diesen funktioniert. Sie ersetzt zeichenfolgenbasierte Pfade, um eine vollständige (absolute) oder partielle (relative) URL für eine Websitesammlung, eine Website, eine Datei, einen Ordner oder ein anderes Artefakt und OneDrive for Business darzustellen. Um % und # in URLs korrekt zu unterstützen, müssen Sie die ResourcePath-basierten APIs zusammen mit decodierten URLs verwenden.
ResourcePath kann einfach durch Aufrufen einer statischen Funktion ResourcePath.FromDecodedUrl(string)
erstellt werden. Auf den übergebenen Eingabewert kann aus dem ResourcePath-Objekt zugegriffen werden, indem die Eigenschaft "DecodedUrl" aufgerufen wird.
Für bestehende Aufrufe, die eine zeichenfolgenbasierte URL aufnehmen, müssen Sie festlegen, ob der Codepfad, der zu zeichenfolgenbasierten URL-Aufrufen führt, mit codierten oder decodierten URLs versehen war und ob diese Codepfade auch Ankerlinks zulassen (d. h. #bookmark-Ergänzungen über der Datei-URL).
Hinweis
Suchen und ersetzen Sie nicht einfach bestehende Verwendungen von zeichenfolgenbasierten URL-APIs durch ResourcePath.FromDecodedUrl
. Sie müssen die URL richtig bestimmen und möglicherweise zuerst URLs decodieren, bevor Sie die ResourcePath.FromDecodedUrl(string)
-API verwenden können.
In Fällen, in denen ein Codepfad, der zu einem zeichenfolgenbasierten SharePoint-API-Aufruf führt, decodierte URLs verwendet hat (z. B. "FY17 Report.docx"), können Sie diese Aufrufe einfach durch ResourcePath.FromDecodedUrl(string)
und gleichwertige ResourcePath-Methoden ersetzen, die später in diesem Artikel behandelt werden.
Beachten Sie, dass in vielen Fällen, in denen Sie die URL aus SharePoint über APIs lesen, auch "ResourcePath" bereitgestellt wird, um diese Codemuster konsistenter zu gestalten, sodass Sie "ResourcePath" anstelle der URL verwenden können.
Beachten Sie außerdem, dass diese Änderung auch für SharePoint REST-basierte Anrufe gilt. In den folgenden Szenarien finden Sie Beispiele für diese neuen APIs in REST.
Neue APIs basierend auf ResourcePath, die # und % unterstützen
Die folgende Tabelle enthält die neuen APIs, die die vorhandenen APIs ersetzen, um # und % zu unterstützen. Wir haben die alten und neuen APIs jeweils zu Vergleichszwecken nebeneinander aufgelistet. Die Kernfunktionen dieser APIs ändern sich nicht, aber die Darstellung der Position des Elements ändert sich.
Eine Dokumentation zu den neuen APIs finden Sie unter .NET-Client-API-Referenz für SharePoint Online. Wir haben die .NET-CSOM-APIs aufgelistet, aber die neuen Methoden sind auch in vergleichbarer Form in unseren JavaScript-CSOM-Bibliotheken verfügbar.
Assembly "Microsoft.SharePoint.Client.dll"
Typ | Alte Methode | Neue Methode |
---|---|---|
Microsoft.SharePoint.SPList | AddItem(Microsoft.SharePoint.SPListItemCreationInformation) | AddItemUsingPath(SPListItemCreationInformationUsingPath parameters) |
Microsoft.SharePoint.SPFile | MoveTo(System.String, Microsoft.SharePoint.SPMoveOperations) | MoveToUsingPath(SPResourcePath newPath, SPMoveOperations moveOperations) |
Microsoft.SharePoint.SPFile | CopyTo(System.String, Boolean) | CopyToUsingPath(SPResourcePath newPath, bool overwrite) |
Microsoft.SharePoint.SPFileCollection | GetByUrl(System.String) | GetByPath(SPResourcePath) |
Microsoft.SharePoint.SPFileCollection | Add(System.String, Microsoft.SharePoint.SPTemplateFileType) | AddUsingPath(SPResourcePath, SPFileCollectionAddWithTemplateParameters) |
Microsoft.SharePoint.SPFolder | MoveTo(System.String) | MoveToUsingPath(SPResourcePath newPath) |
Microsoft.SharePoint.SPFolder | AddSubFolder(System.String) | AddSubFolderUsingPath(SPResourcePath leafPath) |
Microsoft.SharePoint.SPFolderCollection | GetByUrl(System.String) | GetByPath(SPResourcePath path) |
Microsoft.SharePoint.SPFolderCollection | Add(System.String) | AddUsingPath(SPResourcePath path, SPFolderCreationInformation parameters) |
AddWithOverwrite(string url, bool overwrite) | ||
Microsoft.SharePoint.SPRemoteWeb | GetFileByServerRelativeUrl(System.String) | GetFileByServerRelativePath(SPResourcePath path) |
Microsoft.SharePoint.SPWeb | GetList(System.String) | GetListUsingPath(SPResourcePath) |
Microsoft.SharePoint.SPWeb | GetListItem(System.String) | GetListItemUsingPath(SPResourcePath) |
Die folgenden CSOM-Objekte geben ResourcePath-Eigenschaften zurück, die in diesen APIs verwendet werden können. Die alte Eigenschaft gibt zwar auch decodierte URLs zurück, aus Gründen der Benutzerfreundlichkeit, Einfachheit und Übersichtlichkeit wird beim Aufruf dieser APIs aber die neue ResourcePath-Eigenschaft bereitgestellt. Die einzige Ausnahme hierzu bildet die SPFolder.WelcomePage-Eigenschaft, die früher sowohl codierte als auch decodierte URLs zurückgab. Diese wird nun über die WelcomePagePath-Eigenschaft eindeutig zurückgegeben.
Typ | Alte Eigenschaft | Neue Eigenschaft |
---|---|---|
Microsoft.SharePoint.SPList | DefaultViewUrl | DefaultViewPath |
Microsoft.SharePoint.SPList | DefaultEditFormUrl | DefaultEditFormPath |
Microsoft.SharePoint.SPList | DefaultNewFormUrl | DefaultNewFormPath |
Microsoft.SharePoint.SPList | DefaultDisplayFormUrl | DefaultDisplayFormPath |
Microsoft.SharePoint.SPAttachment | ServerRelativeUrl | ServerRelativePath |
Microsoft.SharePoint.SPFile | ServerRelativeUrl | ServerRelativePath |
Microsoft.SharePoint.SPFolder | ServerRelativeUrl | ServerRelativePath |
Microsoft.SharePoint.SPFolder | WelcomePage | WelcomePagePath/ WelcomePageParameters |
Microsoft.SharePoint.SPView | ServerRelativeUrl | ServerRelativePath |
Microsoft.SharePoint.SPDocumentLibraryInformation | ServerRelativeUrl | ServerRelativePath |
Vorhandene APIs, die über das URL-Format nicht mehrdeutig sind und # und % unterstützen können
Die folgenden APIs akzeptieren nur korrekt codierte URLs als Eingabe. Sie unterstützen auch untercodierte URLs, solange die URL ohne jede Mehrdeutigkeit verarbeitet werden kann. Mit anderen Worten, mindestens #- oder %-Zeichen im Pfad der URL sollten %-codiert sein. Diese APIs funktionieren weiterhin wie bisher. #
in der URL wird als Fragmenttrennzeichen und nicht als Teil des URL-Pfads behandelt.
Typ | Alte Eigenschaft |
---|---|
Microsoft.SharePoint.SPWeb | GetFileByUrl(System.String) |
Microsoft.SharePoint.SPWeb | GetFileByWOPIFrameUrl(System.String) |
Microsoft.SharePoint.SPWeb | GetFileByLinkingUrl(System.String) |
Die folgenden C#-Eigenschaften werden hinzugefügt, um "System.Uri" mit eindeutiger Codierung für die Verwendung mit den oben genannten APIs zurückzugeben. Die älteren Varianten der folgenden APIs lieferten decodierte URLs zurück, und da sie nie #- oder %-Zeichen enthielten, war die URL nicht mehrdeutig. Wir wollten das decodierte Verhalten der älteren Varianten für die Zukunft nicht aufheben, um %- und #-Zeichen im Pfad zu codieren. Daher wurden neue APIs erstellt.
Typ | Alte Eigenschaft | Neue Eigenschaft |
---|---|---|
Microsoft.SharePoint.SPFile | LinkingUrl | LinkingUri |
Microsoft.SharePoint.SPFile | ServerRedirectedEmbedUrl | ServerRedirectedEmbedUri |
Beispielcode
CSOM-Szenarien
Hinzufügen einer Datei zu einem Ordner (.net)
ClientContext context = new ClientContext("http://site");
Web web = context.Web;
// Get the parent folder
ResourcePath folderPath = ResourcePath.FromDecodedUrl("/Shared Documents");
Folder parentFolder = web.GetFolderByServerRelativePath(folderPath);
// Create the parameters used to add a file
ResourcePath filePath = ResourcePath.FromDecodedUrl("/Shared Documents/hello world.txt");
byte[] fileContent = System.Text.Encoding.UTF8.GetBytes("sample file content");
FileCollectionAddParameters fileAddParameters = new FileCollectionAddParameters();
fileAddParameters.Overwrite = true;
using (MemoryStream contentStream = new MemoryStream(fileContent))
{
// Add a file
Microsoft.SharePoint.Client.File addedFile = parentFolder.Files.AddUsingPath(filePath, fileAddParameters, contentStream);
// Select properties of added file to inspect
context.Load(addedFile, f => f.UniqueId, f1 => f1.ServerRelativePath);
// Perform the actual operation
context.ExecuteQuery();
// Print the results
Console.WriteLine(
"Added File [UniqueId:{0}] [ServerRelativePath:{1}]",
addedFile.UniqueId,
addedFile.ServerRelativePath.DecodedUrl);
}
Hinzufügen eines Unterordners zu einem Ordner (.net)
ClientContext context = new ClientContext("http://site");
Web web = context.Web;
// Get the parent folder
ResourcePath folderPath = ResourcePath.FromDecodedUrl("Shared Documents");
Folder parentFolder = web.GetFolderByServerRelativePath(folderPath);
// Create the parameters used to add a folder
ResourcePath subFolderPath = ResourcePath.FromDecodedUrl("Shared Documents/sub folder");
FolderCollectionAddParameters folderAddParameters = new FolderCollectionAddParameters();
folderAddParameters.Overwrite = true;
// Add a sub folder
Folder addedFolder = parentFolder.Folders.AddUsingPath(subFolderPath, folderAddParameters);
// Select properties of added file to inspect
context.Load(addedFolder, f => f.UniqueId, f1 => f1.ServerRelativePath);
// Perform the actual operation
context.ExecuteQuery();
// Print the results
Console.WriteLine(
"Added Folder [UniqueId:{0}] [ServerRelativePath:{1}]",
addedFolder.UniqueId,
addedFolder.ServerRelativePath.DecodedUrl);
Abrufen einer Datei im Web (.net)
ClientContext context = new ClientContext("http://site");
Web web = context.Web;
// Get the file
ResourcePath filePath = ResourcePath.FromDecodedUrl("/Shared Documents/hello world.txt");
File file = web.GetFileByServerRelativePath(filePath);
// Select properties of the file
context.Load(file, f => f.UniqueId, f1 => f1.ServerRelativePath);
// Perform the actual operation
context.ExecuteQuery();
// Print the results
Console.WriteLine(
"File Properties [UniqueId:{0}] [ServerRelativePath:{1}]",
file.UniqueId,
file.ServerRelativePath.DecodedUrl);
REST-Szenarien
Abrufen von Ordnern
url: http://site url/_api/web/GetFolderByServerRelativePath(decodedUrl='library name/folder name')
method: GET
headers:
Authorization: "Bearer " + accessToken
accept: "application/json;odata=verbose" or "application/atom+xml"
Erstellen von Ordnern
url: http://site url/_api/web/Folders/AddUsingPath(decodedurl='/document library relative url/folder name')
method: POST
headers:
Authorization: "Bearer " + accessToken
X-RequestDigest: form digest value
accept: "application/json;odata=verbose"
content-type: "application/json;odata=verbose"
Abrufen von Dateien
url: http://site url/_api/web/GetFileByServerRelativePath(decodedUrl='folder name/file name')
method: GET
Headers:
Authorization: "Bearer " + accessToken
accept: "application/json;odata=verbose" or "application/atom+xml"
Hinzufügen von Dateien
url: http://site url/_api/web/GetFolderByServerRelativePath(decodedUrl='folder name')/Files/AddStubUsingPath(decodedurl='testfile.txt')
methods: POST
Headers:
Authorization: "Bearer " + accessToken
X-RequestDigest: form digest value
accept: "application/json;odata=verbose"
content-type: "application/json;odata=verbose"
Content-Length: length