Upload
Enviar arquivos para a API e salvar em pasta ou na base de dados.
Introdução
Quando precisamos enviar arquivos para os serviços da API REST temos várias formas de realizar este desenvolvimento no Netuno.
Normalmente os arquivos são enviados no corpo do pedido HTTP estruturados no formato multipart, é o procedimento mais comum no frontend, por exemplo quando preenchemos um formulário e tem aquele campo para escolher um arquivo.
Em alternativa podemos enviar os bytes dos arquivos codificados em Base64 como valor em um objeto JSON, quando queremos uma API REST 100% JSON.
Arquivos
Através do _req.file podemos passar o nome do campo e assim obter o objeto do arquivo
que foi enviado, veja como:
- JavaScript
- Python
- Ruby
- Kotlin
- Groovy
const meuArquivo = _req.file("arquivo")
meuArquivo = _req.file("arquivo")
meuArquivo = _req.file("arquivo")
val meuArquivo = _req.file("arquivo")
final meuArquivo = _req.file("arquivo")
Ou seja, o _req tem todos os dados que recebemos no corpo do pedido HTTP.
E através do método file permite obter o objeto que representa o arquivo que foi
enviado.
O valor obtido poderá ser null caso não haja nenhum arquivo.
Imagens
Quando recebemos imagens é comum haver a necessidade para redimenciona-la, para garantir uniformidade e para reduzir o espaço ocupado pelas imagens.
- JavaScript
- Python
- Ruby
- Kotlin
- Groovy
const meuArquivo = _req.getFile("imagem")
if (meuArquivo != null
&& (meuArquivo.isExtension("jpeg")
|| meuArquivo.isExtension("jpg")
|| meuArquivo.isExtension("png")
)) {
const minhaImagem = _image.init(meuArquivo)
.resize(200, 200)
.file(meuArquivo.baseName() +".jpg", "jpeg")
_header.contentTypeJPG()
_out.copy(minhaImagem)
}
meuArquivo = _req.getFile("imagem")
if meuArquivo is not None and (
meuArquivo.isExtension("jpeg")
or meuArquivo.isExtension("jpg")
or meuArquivo.isExtension("png")):
minhaImagem = (
_image.init(meuArquivo)
.resize(200, 200)
.file(meuArquivo.baseName() +".jpg", "jpeg")
)
_header.contentTypeJPG()
_out.copy(minhaImagem)
meuArquivo = _req.getFile("imagem")
if !meuArquivo.nil? && (
meuArquivo.isExtension("jpeg") ||
meuArquivo.isExtension("jpg") ||
meuArquivo.isExtension("png")
)
minhaImagem = _image.init(meuArquivo)
.resize(200, 200)
.file(meuArquivo.baseName() +".jpg", "jpeg")
_header.contentTypeJPG()
_out.copy(minhaImagem)
end
val meuArquivo = _req.getFile("imagem")
if (meuArquivo != null
&& (meuArquivo.isExtension("jpeg")
|| meuArquivo.isExtension("jpg")
|| meuArquivo.isExtension("png")
)) {
val minhaImagem = _image.init(meuArquivo.input())
.resize(200, 200)
.file(meuArquivo.baseName() +".jpg", "jpeg")
_header.contentTypeJPG()
_out.copy(minhaImagem.input())
}
final meuArquivo = _req.getFile("imagem")
if (meuArquivo != null
&& (meuArquivo.isExtension("jpeg")
|| meuArquivo.isExtension("jpg")
|| meuArquivo.isExtension("png")
)) {
final minhaImagem = _image.init(meuArquivo)
.resize(200, 200)
.file(meuArquivo.baseName() +".jpg", "jpeg")
_header.contentTypeJPG()
_out.copy(minhaImagem)
}
Com o recurso de programação low-code poliglota Image, podemos manipular imagens, cortar, redimencionar, criar novas, etc.
Como Base64 no JSON
Para realizar o upload de um arquivo no JSON enviado para o serviço, podemos definir uma propriedade com o valor:
data:image/png;base64,...
Onde nos ... segue a sequência dos bytes do arquivo codificados em Base64.
Sendo que o tipo do arquivo vai a seguir ao data, por exemplo:
- PNG:
image/png. - JPG:
image/jpeg - TXT:
text/plain - PDF:
application/pdf - XLSX:
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
Veja o exemplo de um arquivo de uma imagem PNG pequena sendo enviada no JSON para um serviço:
{
"file": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAYAAABWKLW/AAAFIGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS41LjAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iCiAgICB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iCiAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIKICAgZXhpZjpDb2xvclNwYWNlPSIxIgogICBleGlmOlBpeGVsWERpbWVuc2lvbj0iMyIKICAgZXhpZjpQaXhlbFlEaW1lbnNpb249IjMiCiAgIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiCiAgIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIKICAgdGlmZjpJbWFnZUxlbmd0aD0iMyIKICAgdGlmZjpJbWFnZVdpZHRoPSIzIgogICB0aWZmOlJlc29sdXRpb25Vbml0PSIyIgogICB0aWZmOlhSZXNvbHV0aW9uPSI3Mi8xIgogICB0aWZmOllSZXNvbHV0aW9uPSI3Mi8xIgogICB4bXA6TWV0YWRhdGFEYXRlPSIyMDI1LTEyLTI5VDE5OjEyOjI3WiIKICAgeG1wOk1vZGlmeURhdGU9IjIwMjUtMTItMjlUMTk6MTI6MjdaIj4KICAgPHhtcE1NOkhpc3Rvcnk+CiAgICA8cmRmOlNlcT4KICAgICA8cmRmOmxpCiAgICAgIHhtcE1NOmFjdGlvbj0icHJvZHVjZWQiCiAgICAgIHhtcE1NOnNvZnR3YXJlQWdlbnQ9IkFmZmluaXR5IERlc2lnbmVyIDEuMTAuNSIKICAgICAgeG1wTU06d2hlbj0iMjAyNS0wMi0yM1QyMjoxNDozM1oiLz4KICAgICA8cmRmOmxpCiAgICAgIHN0RXZ0OmFjdGlvbj0icHJvZHVjZWQiCiAgICAgIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFmZmluaXR5IDMuMC4xIgogICAgICBzdEV2dDp3aGVuPSIyMDI1LTEyLTI5VDE5OjEyOjI3WiIvPgogICAgPC9yZGY6U2VxPgogICA8L3htcE1NOkhpc3Rvcnk+CiAgPC9yZGY6RGVzY3JpcHRpb24+CiA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgo8P3hwYWNrZXQgZW5kPSJyIj8+UGhcxwAAAYFpQ0NQc1JHQiBJRUM2MTk2Ni0yLjEAACiRdZG7SwNBEIe/JEqCRhS0sFAIEq3iG4I2ggmigkiIEXw1yZmHkMdxlyDBVrANKIg2vgr9C7QVrAVBUQSx1lbRRuWc84QEMbPMzre/3Rl2Z8EeSSsZvaYPMtm8Fh4PeObmFzzOZ9y004yL3qiiq6Oh0BRV7f0Wmxmvu81a1c/9a/XLcV0Bm0t4RFG1vPCE8NRqXjV5S7hFSUWXhU+EfZpcUPjG1GMWP5mctPjTZC0SDoK9SdiTrOBYBSspLSMsL8ebSReU3/uYL3HHs7MzEjvE29AJM04AD5OMEcRPP8My++lmgB5ZUSW/7yd/mpzkKjKrFNFYIUmKPD5RC1I9LjEhelxGmqLZ/7991RODA1Z1dwBqHw3jtROcm/BVMoyPA8P4OgTHA5xny/m5fRh6E71U1rx70LgOpxdlLbYNZxvQeq9GteiP5BC3JxLwcgwN89B8BXWLVs9+9zm6g8iafNUl7OxCl5xvXPoGe8Rn71E5kqUAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAySURBVAiZAScA2P8BJYrEogr//l3h5+qlBP4HCF3n/AAA/wP7WwLu7PKk+eHWAPzWyKSmfRbbIj23ZQAAAABJRU5ErkJggg=="
}
Podemos obter o arquivo enviado da seguinte forma:
- JavaScript
- Python
- Ruby
- Kotlin
- Groovy
const meuArquivo = _req.getFile("file")
if (meuArquivo) {
_out.json(
_val.map()
.set("result", true)
.set("name", meuArquivo.name())
.set("sizeBytes", meuArquivo.size())
.set("sizeKB", meuArquivo.sizeKB())
)
} else {
_out.json(
_val.map()
.set('result', false)
)
}
meuArquivo = _req.getFile("file")
if (meuArquivo) {
_out.json(
_val.map()
.set("result", True)
.set("name", meuArquivo.name())
.set("sizeBytes", meuArquivo.size())
.set("sizeKB", meuArquivo.sizeKB())
)
} else {
_out.json(
_val.map()
.set('result', false)
)
}
meuArquivo = _req.getFile("file")
if (meuArquivo) {
_out.json(
_val.map()
.set("result", true)
.set("name", meuArquivo.name())
.set("sizeBytes", meuArquivo.size())
.set("sizeKB", meuArquivo.sizeKB())
)
} else {
_out.json(
_val.map()
.set('result', false)
)
}
val meuArquivo = _req.getFile("file")
if (meuArquivo) {
_out.json(
_val.map()
.set("result", true)
.set("name", meuArquivo.name())
.set("sizeBytes", meuArquivo.size())
.set("sizeKB", meuArquivo.sizeKB())
)
} else {
_out.json(
_val.map()
.set('result', false)
)
}
final meuArquivo = _req.getFile("file")
if (meuArquivo) {
_out.json(
_val.map()
.set("result", true)
.set("name", meuArquivo.name())
.set("sizeBytes", meuArquivo.size())
.set("sizeKB", meuArquivo.sizeKB())
)
} else {
_out.json(
_val.map()
.set('result', false)
)
}
Exemplo do output gerado pelo serviço acima:
{
"name": "file.png",
"result": true,
"size": 1849,
"sizeKB": 1
}
Objeto
Se o arquivo estiver numa estrutura interna do JSON dentro do subobjeto:
{
"person": {
"file": "data:image/png;base64,..."
}
}
Pode ser obtido da seguinte forma:
- JavaScript
- Python
- Ruby
- Kotlin
- Groovy
const meuArquivo = _req.getValues("person").getFile("avatar")
meuArquivo = _req.getValues("person").getFile("avatar")
meuArquivo = _req.getValues("person").getFile("avatar")
val meuArquivo = _req.getValues("person").getFile("avatar")
final meuArquivo = _req.getValues("person").getFile("avatar")
Array
Caso o arquivo estiver numa estrutura interna do JSON dentro do array:
{
"files": [
"data:image/png;base64,..."
]
}
Pode ser obtido da seguinte forma:
- JavaScript
- Python
- Ruby
- Kotlin
- Groovy
const meuArquivo = _req.getValues("files").getFile(0)
meuArquivo = _req.getValues("files").getFile(0)
meuArquivo = _req.getValues("files").getFile(0)
val meuArquivo = _req.getValues("files").getFile(0)
final meuArquivo = _req.getValues("files").getFile(0)
OpenAPI
O Netuno suporta a integração com a OpenAPI e utiliza a definição da OpenAPI para validar o pedido HTTP.
Mais sobre a OpenAPI no Netuno.
Com o tipo file o Netuno valida se o valor começa com o formato de arquivo no JSON, por exemplo:
data:image/png;base64,...
Para validar se está recebendo um arquivo em uma propriedade do objeto JSON:
{
"summary": "Upload de Arquivo",
"description": "Serviço que recebe um arquivo no objeto JSON.",
"type": "object",
"properties": {
"file": {
"type": "file"
}
},
"required": [
"file"
]
}
Para validar se está recebendo uma lista de arquivos em array no JSON:
{
"summary": "Upload de Arquivos",
"description": "Serviço que recebe uma lista de arquivos em array no JSON.",
"properties": {
"files": {
"type": "array",
"items": {
"type": "file"
}
}
},
"required": [
"files"
]
}
Salvar o Arquivo
Normalmente quando recebemos um arquivo no serviço precisamos salvá-lo, como por exemplo:
- Base de dados: Arquivo relacionado a um registro, como de um usuário.
- Storage: Pasta interna da aplicação que serve para gerir arquivos no geral.
- Pasta: Colocar o arquivo em uma pasta qualquer do sistema.
Base de Dados
Na gestão dos campos dos formulários, o Netuno suporta o tipo image e file, sendo:
- Image: Arquivos de imagem no geral, JPG e PNG.
- File: Qualquer tipo de arquivo.
Imagine que tem um campo de Imagem no formulário Produto, podemos fazer salvar o arquivo enviado via upload da seguinte forma:
Exemplo utilizando o DB Form:
Repare na utilização do _db.form:
- JavaScript
- Python
- Ruby
- Kotlin
- Groovy
const produtoUid = _req.getString("uid")
const produtoImagem = _req.getFile("imagem")
if (produtoImagem == null) {
_header.status(400)
_out.json(
_val.map()
.set("result", false)
.set("error", "imagem-obrigatória")
)
_exec.stop()
}
const dbResultado = _db.form("produto")
.set("imagem", produtoImagem)
.where(_db.where("uid").equals(produtoUid))
.update()
if (dbResultado.getInt("produto") == 1) {
_out.json(
_val.map()
.set("result", true)
)
} else {
_header.status(404)
_out.json(
_val.map()
.set("result", false)
.set("error", "uid-produto-não-existe")
)
}
produtoUid = _req.getString("uid")
produtoImagem = _req.getFile("imagem")
if produtoImagem is None:
_header.status(400)
_out.json(
_val.map()
.set("result", False)
.set("error", "imagem-obrigatória")
)
_exec.stop()
dbResultado = (
_db.form("produto")
.set("imagem", produtoImagem)
.where(_db.where("uid").equals(produtoUid))
.update()
)
if dbResultado.getInt("produto") == 1:
_out.json(
_val.map()
.set("result", True)
)
else:
_header.status(404)
_out.json(
_val.map()
.set("result", False)
.set("error", "uid-produto-não-existe")
)
produto_uid = _req.getString("uid")
produto_imagem = _req.getFile("imagem")
if produto_imagem.nil?
_header.status = 400
_out.json(
_val.map()
.set("result", false)
.set("error", "imagem-obrigatória")
)
_exec.stop
end
db_resultado = _db.form("produto")
.set("imagem", produto_imagem)
.where(_db.where("uid").equals(produto_uid))
.update()
if db_resultado.getInt("produto") == 1
_out.json(
_val.map()
.set("result", true)
)
else
_header.status = 404
_out.json(
_val.map()
.set("result", false)
.set("error", "uid-produto-não-existe")
)
end
val produtoUid = _req.getString("uid")
val produtoImagem = _req.getFile("imagem")
if (produtoImagem == null) {
_header.status(400)
_out.json(
_val.map()
.set("result", false)
.set("error", "imagem-obrigatória")
)
_exec.stop()
}
val dbResultado = _db.form("produto")
.set("imagem", produtoImagem)
.where(_db.where("uid").equals(produtoUid))
.update()
if (dbResultado.getInt("produto") == 1) {
_out.json(
_val.map()
.set("result", true)
)
} else {
_header.status(404)
_out.json(
_val.map()
.set("result", false)
.set("error", "uid-produto-não-existe")
)
}
final produtoUid = _req.getString("uid")
final produtoImagem = _req.getFile("imagem")
if (produtoImagem == null) {
_header.status(400)
_out.json(
_val.map()
.set("result", false)
.set("error", "imagem-obrigatória")
)
_exec.stop()
}
final dbResultado = _db.form("produto")
.set("imagem", produtoImagem)
.where(_db.where("uid").equals(produtoUid))
.update()
if (dbResultado.getInt("produto") == 1) {
_out.json(
_val.map()
.set("result", true)
)
} else {
_header.status(404)
_out.json(
_val.map()
.set("result", false)
.set("error", "uid-produto-não-existe")
)
}
Exemplo utilizando o update clássico:
Repare na utilização do _db.update:
- JavaScript
- Python
- Ruby
- Kotlin
- Groovy
const produtoUid = _req.getString("uid")
const produtoImagem = _req.getFile("imagem")
if (produtoImagem == null) {
_header.status(400)
_out.json(
_val.map()
.set("result", false)
.set("error", "imagem-obrigatória")
)
_exec.stop()
}
const dbResultado = _db.update(
"produto",
produtoUid,
_val.map()
.set("imagem", produtoImagem)
)
if (dbResultado == 1) {
_out.json(
_val.map()
.set("result", true)
)
} else {
_header.status(404)
_out.json(
_val.map()
.set("result", false)
.set("error", "uid-produto-não-existe")
)
}
produtoUid = _req.getString("uid")
produtoImagem = _req.getFile("imagem")
if produtoImagem is None:
_header.status(400)
_out.json(
_val.map()
.set("result", False)
.set("error", "imagem-obrigatória")
)
_exec.stop()
dbResultado = (
_db.update(
"produto",
produtoUid,
_val.map()
.set("imagem", produtoImagem)
)
)
if dbResultado == 1:
_out.json(
_val.map()
.set("result", True)
)
else:
_header.status(404)
_out.json(
_val.map()
.set("result", False)
.set("error", "uid-produto-não-existe")
)
produto_uid = _req.getString("uid")
produto_imagem = _req.getFile("imagem")
if produto_imagem.nil?
_header.status = 400
_out.json(
_val.map()
.set("result", false)
.set("error", "imagem-obrigatória")
)
_exec.stop
end
db_resultado = _db.update(
"produto",
produto_uid,
_val.map()
.set("imagem", produto_imagem)
)
if db_resultado == 1
_out.json(
_val.map()
.set("result", true)
)
else
_header.status = 404
_out.json(
_val.map()
.set("result", false)
.set("error", "uid-produto-não-existe")
)
end
val produtoUid = _req.getString("uid")
val produtoImagem = _req.getFile("imagem")
if (produtoImagem == null) {
_header.status(400)
_out.json(
_val.map()
.set("result", false)
.set("error", "imagem-obrigatória")
)
_exec.stop()
}
val dbResultado = _db.update(
"produto",
produtoUid,
_val.map()
.set("imagem", produtoImagem)
)
if (dbResultado == 1) {
_out.json(
_val.map()
.set("result", true)
)
} else {
_header.status(404)
_out.json(
_val.map()
.set("result", false)
.set("error", "uid-produto-não-existe")
)
}
final produtoUid = _req.getString("uid")
final produtoImagem = _req.getFile("imagem")
if (produtoImagem == null) {
_header.status(400)
_out.json(
_val.map()
.set("result", false)
.set("error", "imagem-obrigatória")
)
_exec.stop()
}
final dbResultado = _db.update(
"produto",
produtoUid,
_val.map()
.set("imagem", produtoImagem)
)
if (dbResultado == 1) {
_out.json(
_val.map()
.set("result", true)
)
} else {
_header.status(404)
_out.json(
_val.map()
.set("result", false)
.set("error", "uid-produto-não-existe")
)
}
Download do Arquivo da Base de Dados
Para apresentar o arquivo armazenado devemos criar um serviço que fornece os bytes do arquivo.
Sendo que os arquivos salvados em base de dados, como no exemplo acima, o arquivo em si é colocado no storage da aplicação e na base de dados fica armazenado apenas o nome final do arquivo.
O storage da aplicação é uma pasta destinada a armazenar e organizar estruturas de arquivos genéricos.
Portanto, no exemplo acima os arquivos de base de dados do formulário Produto e do campo Imagem ficam
armazenados em:
storage/database/produto/imagem/*
O Netuno automaticamente gere o nome do arquivo armazenado para evitar nomes de arquivos repetidos.
Para obter o arquivo, pode ser criado um serviço que apresenta o arquivo de imagem do produto, por exemplo:
- JavaScript
- Python
- Ruby
- Kotlin
- Groovy
const produtoUid = _req.getString("uid")
// DB Form:
const dbProduto = _db.form("produto")
.where(_db.where("uid").equals(produtoUid))
.first()
// Alternativa com DB Clássico:
// const dbProduto = _db.get("produto", produtoUid)
if (dbProduto == null) {
_header.status(404)
_out.json(
_val.map()
.set("result", false)
.set("error", "produto-nao-encontrado")
)
_exec.stop()
}
const dbProdutoImagemNome = dbProduto.getString("imagem")
const storageProdutoImagemArquivo = _storage.database(
"produto",
"imagem",
dbProdutoImagemNome
)
if (storageProdutoImagemArquivo.extension() == "jpg" || storageProdutoImagemArquivo.extension() == "jpeg") {
_header.contentTypeJPG()
} else {
_header.contentTypePNG()
}
_header.noCache()
_out.copy(storageProdutoImagemArquivo.inputStream())
produtoUid = _req.getString("uid")
# DB Form:
dbProduto = (
_db.form("produto")
.where(_db.where("uid").equals(produtoUid))
.first()
)
# Alternativa com DB Clássico:
# dbProduto = _db.get("produto", produtoUid)
if dbProduto is None:
_header.status(404)
_out.json(
_val.map()
.set("result", False)
.set("error", "produto-nao-encontrado")
)
_exec.stop()
dbProdutoImagemNome = dbProduto.getString("imagem")
storageProdutoImagemArquivo = _storage.database(
"produto",
"imagem",
dbProdutoImagemNome
)
if storageProdutoImagemArquivo.extension() == "jpg" or storageProdutoImagemArquivo.extension() == "jpeg":
_header.contentTypeJPG()
else:
_header.contentTypePNG()
_header.noCache()
_out.copy(storageProdutoImagemArquivo.inputStream())
produtoUid = _req.getString("uid")
# DB Form:
dbProduto = _db.form("produto")
.where(_db.where("uid").equals(produtoUid))
.first()
# Alternativa com DB Clássico:
# dbProduto = _db.get("produto", produtoUid)
if dbProduto.nil?
_header.status(404)
_out.json(
_val.map()
.set("result", false)
.set("error", "produto-nao-encontrado")
)
_exec.stop()
end
dbProdutoImagemNome = dbProduto.getString("imagem")
storageProdutoImagemArquivo = _storage.database(
"produto",
"imagem",
dbProdutoImagemNome
)
if storageProdutoImagemArquivo.extension() == "jpg" || storageProdutoImagemArquivo.extension() == "jpeg"
_header.contentTypeJPG()
else
_header.contentTypePNG()
end
_header.noCache()
_out.copy(storageProdutoImagemArquivo.inputStream())
val produtoUid = _req.getString("uid")
// DB Form:
val dbProduto = _db.form("produto")
.where(_db.where("uid").equals(produtoUid))
.first()
// Alternativa com DB Clássico:
// val dbProduto = _db.get("produto", produtoUid)
if (dbProduto == null) {
_header.status(404)
_out.json(
_val.map()
.set("result", false)
.set("error", "produto-nao-encontrado")
)
_exec.stop()
}
val dbProdutoImagemNome = dbProduto.getString("imagem")
val storageProdutoImagemArquivo = _storage.database(
"produto",
"imagem",
dbProdutoImagemNome
)
if (storageProdutoImagemArquivo.extension() == "jpg" || storageProdutoImagemArquivo.extension() == "jpeg") {
_header.contentTypeJPG()
} else {
_header.contentTypePNG()
}
_header.noCache()
_out.copy(storageProdutoImagemArquivo.inputStream())
final produtoUid = _req.getString("uid")
// DB Form:
final dbProduto = _db.form("produto")
.where(_db.where("uid").equals(produtoUid))
.first()
// Alternativa com DB Clássico:
// final dbProduto = _db.get("produto", produtoUid)
if (dbProduto == null) {
_header.status(404)
_out.json(
_val.map()
.set("result", false)
.set("error", "produto-nao-encontrado")
)
_exec.stop()
}
final dbProdutoImagemNome = dbProduto.getString("imagem")
final storageProdutoImagemArquivo = _storage.database(
"produto",
"imagem",
dbProdutoImagemNome
)
if (storageProdutoImagemArquivo.extension() == "jpg" || storageProdutoImagemArquivo.extension() == "jpeg") {
_header.contentTypeJPG()
} else {
_header.contentTypePNG()
}
_header.noCache()
_out.copy(storageProdutoImagemArquivo.inputStream())
Repare que o recurso _storage é utilizado para obter o arquivo:
- JavaScript
- Python
- Ruby
- Kotlin
- Groovy
_storage.database(
"produto", // Nome do formulário/tabela.
"imagem", // Nome do campo/coluna.
dbProdutoImagemNome // Nome do arquivo.
)
_storage.database(
"produto", # Nome do formulário/tabela.
"imagem", # Nome do campo/coluna.
dbProdutoImagemNome # Nome do arquivo.
)
_storage.database(
"produto", # Nome do formulário/tabela.
"imagem", # Nome do campo/coluna.
dbProdutoImagemNome # Nome do arquivo.
)
_storage.database(
"produto", // Nome do formulário/tabela.
"imagem", // Nome do campo/coluna.
dbProdutoImagemNome // Nome do arquivo.
)
_storage.database(
"produto", // Nome do formulário/tabela.
"imagem", // Nome do campo/coluna.
dbProdutoImagemNome // Nome do arquivo.
)
Repare que na base de dados fica armazenado apenas o nome do arquivo, sendo que através do _storage.database
podemos obter o arquivo em si.
Storage
Podemos salvar um arquivo diretamente no storage da aplicação.
Para não misturar com os arquivos de base de dados, devemos utilizar a pasta de filesystem, que tem a
finalidade de armazenar arquivos genéricos que não estão associados na base de dados.
Para receber o arquivo, neste exemplo é demonstrado como um arquivo enviado no serviço
POST é armazenado diretamente no storage:
- JavaScript
- Python
- Ruby
- Kotlin
- Groovy
const arquivo = _req.getFile("arquivo")
_storage.filesystem("server", "upload").ensurePath()
arquivo.save(_storage.filesystem("server", "upload", arquivo.name()))
arquivo = _req.getFile("arquivo")
_storage.filesystem("server", "upload").ensurePath()
arquivo.save(_storage.filesystem("server", "upload", arquivo.name()))
arquivo = _req.getFile("arquivo")
_storage.filesystem("server", "upload").ensurePath()
arquivo.save(_storage.filesystem("server", "upload", arquivo.name()))
val arquivo = _req.getFile("arquivo")
_storage.filesystem("server", "upload").ensurePath()
arquivo.save(_storage.filesystem("server", "upload", arquivo.name()))
final arquivo = _req.getFile("arquivo")
_storage.filesystem("server", "upload").ensurePath()
arquivo.save(_storage.filesystem("server", "upload", arquivo.name()))
O arquivo fica armazenado na pasta storage da aplicação, em:
storage/filesystem/server/upload/*
Repare que o recurso _storage é utilizado para obter o caminho de pasta e de arquivo:
- JavaScript
- Python
- Ruby
- Kotlin
- Groovy
_storage.filesystem(
"server", // Nome da subpasta no filesystem.
"upload", // Nome da outra subpasta.
arquivo.name() // Nome final do arquivo.
)
_storage.filesystem(
"server", # Nome da subpasta no filesystem.
"upload", # Nome da outra subpasta.
arquivo.name() # Nome final do arquivo.
)
_storage.filesystem(
"server", # Nome da subpasta no filesystem.
"upload", # Nome da outra subpasta.
arquivo.name() # Nome final do arquivo.
)
_storage.filesystem(
"server", // Nome da subpasta no filesystem.
"upload", // Nome da outra subpasta.
arquivo.name() // Nome final do arquivo.
)
_storage.filesystem(
"server", // Nome da subpasta no filesystem.
"upload", // Nome da outra subpasta.
arquivo.name() // Nome final do arquivo.
)
Veja mais sobre a documentação do Storage.
Para fazer o download do arquivo, neste exemplo é demonstrado como os bytes do arquivo
podem ser obtidos através do serviço GET:
- JavaScript
- Python
- Ruby
- Kotlin
- Groovy
const arquivoNome = _req.getString("arquivo")
const arquivo = _storage.filesystem(
"server",
"upload",
arquivoNome
).file()
if (arquivo.exists() == false) {
_header.status(404)
_out.json(
_val.map()
.set("result", false)
.set("error", "arquivo-nao-existe")
)
_exec.stop()
}
_header.downloadFile(arquivo.name())
_out.copy(arquivo.input())
arquivoNome = _req.getString("arquivo")
arquivo = _storage.filesystem(
"server",
"upload",
arquivoNome
).file()
if arquivo.exists() == False:
_header.status(404)
_out.json(
_val.map()
.set("result", False)
.set("error", "arquivo-nao-existe")
)
_exec.stop()
_header.downloadFile(arquivo.name())
_out.copy(arquivo.input())
arquivoNome = _req.getString("arquivo")
arquivo = _storage.filesystem(
"server",
"upload",
arquivoNome
).file()
if arquivo.exists() == false
_header.status(404)
_out.json(
_val.map()
.set("result", false)
.set("error", "arquivo-nao-existe")
)
_exec.stop()
end
_header.downloadFile(arquivo.name())
_out.copy(arquivo.input())
val arquivoNome = _req.getString("arquivo")
val arquivo = _storage.filesystem(
"server",
"upload",
arquivoNome
).file()
if (arquivo.exists() == false) {
_header.status(404)
_out.json(
_val.map()
.set("result", false)
.set("error", "arquivo-nao-existe")
)
_exec.stop()
}
_header.downloadFile(arquivo.name())
_out.copy(arquivo.input())
final arquivoNome = _req.getString("arquivo")
final arquivo = _storage.filesystem(
"server",
"upload",
arquivoNome
).file()
if (arquivo.exists() == false) {
_header.status(404)
_out.json(
_val.map()
.set("result", false)
.set("error", "arquivo-nao-existe")
)
_exec.stop()
}
_header.downloadFile(arquivo.name())
_out.copy(arquivo.input())
Pasta
Podemos salvar um arquivo diretamente em qualquer pasta do computador.
Há dois recursos que são muito úteis nestes casos:
_app- Podemos pegar qualquer pasta ou arquivo na aplicação._os- Podemos pegar qualquer pasta ou arquivo no computador.
Veja a documentação dos respectivos recursos App e OS, ambos os recursos tem os métodos
folderefile, que permitem indicar qual o caminho da pasta ou do arquivo respectivamente.
Para receber o arquivo, neste exemplo é demonstrado como um arquivo enviado no serviço
POST é armazenado diretamente em uma pasta na aplicação:
- JavaScript
- Python
- Ruby
- Kotlin
- Groovy
const arquivo = _req.getFile("arquivo")
const pasta = _app.folder("temp")
if (pasta.exists() == false) {
pasta.mkdir()
}
arquivo.save(_app.file(`temp/${arquivo.name()}`))
arquivo = _req.getFile("arquivo")
pasta = _app.folder("temp")
if pasta.exists() == False:
pasta.mkdir()
arquivo.save(_app.file(f"temp/{arquivo.name()}"))
arquivo = _req.getFile("arquivo")
pasta = _app.folder("temp")
if pasta.exists() == false
pasta.mkdir()
end
arquivo.save(_app.file("temp/#{arquivo.name()}"))
val arquivo = _req.getFile("arquivo")
val pasta = _app.folder("temp")
if (pasta.exists() == false) {
pasta.mkdir()
}
arquivo.save(_app.file("temp/${arquivo.name()}"))
final arquivo = _req.getFile("arquivo")
final pasta = _app.folder("temp")
if (pasta.exists() == false) {
pasta.mkdir()
}
arquivo.save(_app.file("temp/${arquivo.name()}"))
O código acima vai criar a pasta temp dentro da aplicação e salvar o arquivo recebido
dentro desta pasta.
Para fazer o download do arquivo, neste exemplo é demonstrado como os bytes do arquivo
podem ser obtidos através do serviço GET:
- JavaScript
- Python
- Ruby
- Kotlin
- Groovy
const arquivoNome = _req.getString("arquivo")
const arquivo = _app.file(`temp/${arquivoNome}`)
if (arquivo.exists() == false) {
_header.status(404)
_out.json(
_val.map()
.set("result", false)
.set("error", "arquivo-nao-existe")
)
_exec.stop()
}
_header.downloadFile(arquivo.name())
_out.copy(arquivo.input())
arquivoNome = _req.getString("arquivo")
arquivo = _app.file(f"temp/{arquivoNome}")
if arquivo.exists() == False:
_header.status(404)
_out.json(
_val.map()
.set("result", False)
.set("error", "arquivo-nao-existe")
)
_exec.stop()
_header.downloadFile(arquivo.name())
_out.copy(arquivo.input())
arquivoNome = _req.getString("arquivo")
arquivo = _app.file("temp/#{arquivoNome}")
if arquivo.exists() == false
_header.status(404)
_out.json(
_val.map()
.set("result", false)
.set("error", "arquivo-nao-existe")
)
_exec.stop()
end
_header.downloadFile(arquivo.name())
_out.copy(arquivo.input())
val arquivoNome = _req.getString("arquivo")
val arquivo = _app.file("temp/${arquivoNome}")
if (arquivo.exists() == false) {
_header.status(404)
_out.json(
_val.map()
.set("result", false)
.set("error", "arquivo-nao-existe")
)
_exec.stop()
}
_header.downloadFile(arquivo.name())
_out.copy(arquivo.input())
final arquivoNome = _req.getString("arquivo")
final arquivo = _app.file("temp/${arquivoNome}")
if (arquivo.exists() == false) {
_header.status(404)
_out.json(
_val.map()
.set("result", false)
.set("error", "arquivo-nao-existe")
)
_exec.stop()
}
_header.downloadFile(arquivo.name())
_out.copy(arquivo.input())
Conclusão
Como pode ser visto podemos integrar o upload de arquivos nos serviços da API REST, inclusive integrado com a OpenAPI.
Podemos salvar o arquivo na base de dados, dentro da pasta storage da aplicação ou em qualquer pasta do
computador.
Veja a documentação dos recursos utilizados neste tutorial que permitem manipular os arquivos:
Em base de dados podemos salvar imagens em campos do tipo image, e podemos salvar qualquer tipo de arquivo em
campos do tipo file, como salvamos ou obtemos arquivos são da mesma forma em qualquer caso, seja imagem ou
arquivo genérico.