Escrito por

Sales Engineer at InterSystems
Artigo Danusa Calixto · jan 11, 2024 3m read

Recuperando arquivos em Base64 de uma chamada POST evitando erros <MAXSTRING>

Sejam todos bem-vindos!

Neste breve artigo, quero apresentar um exemplo de uso que vários de vocês que trabalham com o IRIS como back-end para seus web applications devem ter enfrentado mais de uma vez: como enviar um arquivo do front-end para o servidor.

Em geral, a maneira mais simples que encontrei de realizar essa tarefa é transformar o arquivo do front-end para o formato Base64 e fazer uma chamada POST para o servidor anexando o Base64 obtido a uma mensagem JSON onde é indicado o nome do arquivo em um parâmetro e os dados codificados em outro. Algo parecido com isto:

{
"fileData": "JVBERi0xLjQKJdPr6eEKMSAwIG...",
"fileName": "example.pdf"
}

Da minha instância IRIS, configurei um web application para gerenciar essas chamadas POST de uma classe que estende %CSP.REST. Essa classe tem um classmethod para gerenciar o POST corretamente. O código deve ficar assim:

ClassMethod SaveFile() As %Status
{
Try {
Do ##class(%REST.Impl).%SetContentType("application/json")
If '##class(%REST.Impl).%CheckAccepts("application/json") Do ##class(%REST.Impl).%ReportRESTError(..#HTTP406NOTACCEPTABLE,$$$ERROR($$$RESTBadAccepts)) Quit
// Lendo o corpo da chamada http com os dados do arquivo

    set dynamicBody = {}.%FromJSON(%request.Content)

    set dynamicStream = dynamicBody.%Get("fileData",,"stream&lt;base64")
    
    set stream=##class(%Stream.FileBinary).%New()
    set sc=stream.LinkToFile("/shared/durable/"_dynamicBody.fileName)
    set sc=stream.CopyFromAndSave(dynamicStream)
   
} Catch (ex) {
    Do ##class(%REST.Impl).%SetStatusCode("400")
    Do ##class(%REST.Impl).%WriteResponse(ex.DisplayString())
    return {"errormessage": "Client error"}
}
Quit $$$OK

}

Vamos explicar em detalhes o que esse método está fazendo:

  1. Recebemos o conteúdo enviado no corpo da mensagem e transformamos isso em um %Library.DynamicAbstractObject que pode ser lido como um objeto.
    set dynamicBody = {}.%FromJSON(%request.Content)

     

  2. Essa etapa é onde a mágica acontece. Transformamos nosso Base64 em um tipo %Stream que podemos obter usando o método %Get da classe %Library.DynamicObject.
  3. set dynamicStream = dynamicBody.%Get("fileData",,"stream<base64")
    Como você pode ver, estamos passando como um parâmetro de entrada o tipo de transformação que queremos realizar, em nosso exemplo de Base64 para Stream (stream<base64). Qual é a vantagem de usar essa instrução? Bem, não vamos estar limitados pelo valor MAXSTRING, ou seja, se nosso arquivo em Base64 for muito grande, nunca vamos receber uma exceção porque ultrapassamos o limite máximo de comprimento permitido para uma String.
  4. Por fim, criamos em nosso servidor o arquivo que conterá os dados enviados em Base64 com o nome definido na chamada recebida e escrevemos nosso objeto de tipo %Stream nele.
    set stream=##class(%Stream.FileBinary).%New()
    set sc=stream.LinkToFile("/shared/durable/"_dynamicBody.fileName)
    set sc=stream.CopyFromAndSave(dynamicStream)

Como você pode ver, é muito fácil gerenciar arquivos em Base64 do nosso servidor. Se você tiver dúvidas, não hesite em escrevê-las na seção de comentários. Será um prazer responder.