Compartilhar via


Suporte para % e # em arquivos e pastas com a API do ResourcePath

Está sendo implantado suporte % e # em arquivos e pastas no SharePoint Online. Infelizmente, devido a estruturas de API e padrões de chamada existentes, o trabalho com esses nomes de arquivos pode se tornar ambíguo em alguns casos. Você pode encontrar mais informações sobre isso em nosso blog de desenvolvedores.

Em síntese, novas APIs foram adicionadas à superfície do modelo de objeto de cliente do SharePoint Online (CSOM) para oferecer suporte a caracteres # e %.

Nova classe ResourcePath

Como recapitulação, observe que as APIs do SharePoint baseadas em cadeia de caracteres (como SPFileCollection.GetByUrl) manipulam URLs codificadas e decodificadas assumindo automaticamente que os caracteres % e # em um caminho indicam que a URL foi codificada. Com o novo suporte para% e # em arquivos e pastas, esse tratamento automático se tornou problemático, pois pode fazer com que o código downstream ignore ou manipule incorretamente nomes de arquivos que contenham % e #.

Uma nova classe, Microsoft.SharePoint.Client.ResourcePath, foi adicionada às APIs. A classe ResourcePath é fundamental para o suporte desses novos caracteres. Ela fornece uma maneira de nova e não ambígua de resolver um item no SharePoint e OneDrive for Business, pois considera e funciona somente com URLs decodificadas. Ele substitui os caminhos baseados em cadeia de caracteres a fim de representar uma URL completa (absoluta) ou parcial (relativa) para um conjunto de sites, site, arquivo, pasta ou outro artefato e o OneDrive for Business. Para oferecer suporte corretamente a % e # em URLs, use as APIs baseadas em ResourcePath junto com URLs decodificadas.

ResourcePath pode ser construído simplesmente chamando uma função estática ResourcePath.FromDecodedUrl(string). O valor de entrada transmitido pode ser acessado do objeto ResourcePath chamando a propriedade DecodedUrl.

Para as chamadas existentes que aceitam uma URL baseada em cadeia de caracteres, determine se o caminho do código que leva a chamadas de URL baseadas em cadeia de caracteres foi fornecido com URLs codificadas ou decodificadas e se esses caminhos de código também permitiam links de ancoragem (ou seja: adições #bookmark na URL do arquivo.)

Observação

Não localize e substitua usos existentes de APIs de URL baseada em cadeia de caracteres com ResourcePath.FromDecodedUrl. Você precisará determinar a URL de modo correto e, possivelmente, decodificar URLs antes de usar a API ResourcePath.FromDecodedUrl(string).

Nos casos em que um caminho de código que leva a uma chamada da API do SharePoint baseada em cadeia de caracteres tenha usado URLs decodificadas (por exemplo, “FY17 Report.docx”), você pode simplesmente substituir essas chamadas por ResourcePath.FromDecodedUrl(string) e pelos métodos de ResourcePath equivalentes listados mais adiante neste artigo.

Em muitos casos em que você lê a URL do SharePoint por meio de APIs, o ResourcePath também é fornecido para tornar esses padrões de código mais consistentes, de modo que você possa usar o ResourcePath em vez da URL.

Além disso, observe que essa alteração também se aplica a chamadas baseadas em REST do SharePoint. Confira os seguintes cenários para ver exemplos dessas novas APIs no REST.

Novas APIs baseia no ResourcePath compatíveis com # e %

A tabela a seguir mostra as novas APIs apresentadas para substituir as APIs existentes e oferecer suporte a # e %. Listamos a API antiga e a nova API lado a lado para fins de comparação. A funcionalidade principal dessas APIs não foi alterada, mas a maneira de representar a localização do item sim.

Para ver a documentação sobre as novas APIs, confira Referência da API do cliente .NET para SharePoint Online. Listamos as APIs do .NET CSOM, mas os novos métodos também estão disponíveis de forma equivalente em nossas bibliotecas JavaScript CSOM.

Assembly Microsoft.SharePoint.Client.dll

Tipo Método antigo Novo método
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(caminho SPResourcePath, parâmetros SPFolderCreationInformation)
AddWithOverwrite(url da cadeia de caracteres, substituição de bool)
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)

Os seguintes objetos CSOM retornam propriedades ResourcePath que podem ser usadas nessas APIs. Embora a propriedade antiga também retorne URLs decodificadas, a nova propriedade ResourcePath é fornecida por conveniência, simplicidade e clareza na chamada dessas APIs. A única exceção a isso é a propriedade SPFolder.WelcomePage, que anteriormente retornava URLs codificadas e não codificadas; isso agora é retornado de forma não ambígua por meio da propriedade WelcomePagePath.


Tipo Antiga propriedade Nova propriedade
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

APIs existentes que não são ambíguas quanto ao formato de URL e que são compatíveis com # e %

As APIs a seguir aceitam apenas URLs corretamente codificadas como entrada. Eles também são compatíveis com URLs subcodificados, desde que a URL possa ser consumida sem qualquer ambiguidade. Em outras palavras, pelo menos os caracteres # ou % no caminho da URL devem ser codificados com %. Essas APIs continuarão a funcionar da maneira existente. # na URL é tratado como um delimitador de fragmento, mas não como parte do caminho de URL.

Tipo Antiga propriedade
Microsoft.SharePoint.SPWeb GetFileByUrl(System.String)
Microsoft.SharePoint.SPWeb GetFileByWOPIFrameUrl(System.String)
Microsoft.SharePoint.SPWeb GetFileByLinkingUrl(System.String)

As seguintes propriedades C# são adicionadas para retornar System.Uri com codificação não ambígua para uso com as APIs acima. A variante mais antiga das seguintes APIs retornava URLs decodificadas e, como nunca continham caracteres # ou %, a URL não era ambígua. Prosseguindo, não queríamos quebrar o comportamento decodificado das variantes mais antigas para codificar caracteres % e # no caminho. Portanto, novas APIs foram criadas.

Tipo Antiga propriedade Nova propriedade
Microsoft.SharePoint.SPFile LinkingUrl LinkingUri
Microsoft.SharePoint.SPFile ServerRedirectedEmbedUrl ServerRedirectedEmbedUri

Código de exemplo

Cenários CSOM

Adicionar um arquivo a uma pasta (.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);
 }


Adicionar uma subpasta a uma pasta (.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);

Obter um arquivo na 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);

Cenários REST

Obter pastas

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"


Criar pasta

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"
 

Obter arquivos

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"


Adicionar arquivos

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
 

Confira também