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<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:
- 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) - 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.
-
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.set dynamicStream = dynamicBody.%Get("fileData",,"stream<base64") - 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.