Freigeben über


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
 

Siehe auch