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 <span class="hljs-keyword">set</span> dynamicBody = {}.<span class="hljs-built_in">%FromJSON</span>(<span class="hljs-built_in">%request.Content</span>)
<span class="hljs-keyword">set</span> dynamicStream = dynamicBody.<span class="hljs-built_in">%Get</span>(<span class="hljs-string">"fileData"</span>,,<span class="hljs-string">"stream<base64"</span>)
<span class="hljs-keyword">set</span> stream=<span class="hljs-keyword">##class</span>(<span class="hljs-built_in">%Stream.FileBinary</span>).<span class="hljs-built_in">%New</span>()
<span class="hljs-keyword">set</span> sc=stream.LinkToFile(<span class="hljs-string">"/shared/durable/"</span>_dynamicBody.fileName)
<span class="hljs-keyword">set</span> sc=stream.CopyFromAndSave(dynamicStream)
} <span class="hljs-keyword">Catch</span> (ex) {
<span class="hljs-keyword">Do</span> <span class="hljs-keyword">##class</span>(<span class="hljs-built_in">%REST.Impl</span>).<span class="hljs-built_in">%SetStatusCode</span>(<span class="hljs-string">"400"</span>)
<span class="hljs-keyword">Do</span> <span class="hljs-keyword">##class</span>(<span class="hljs-built_in">%REST.Impl</span>).<span class="hljs-built_in">%WriteResponse</span>(ex.DisplayString())
<span class="hljs-keyword">return</span> {<span class="hljs-string">"errormessage"</span>: <span class="hljs-string">"Client error"</span>}
}
<span class="hljs-keyword">Quit</span> <span class="hljs-built_in">$$$OK</span>
}
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.