Inserir imagem em api
[Finalizado Pelo Aluno]
Professor Carlos, como faço inserção de uma imagem na api, atraves do Vue3?
Olá, Renato!
Como vai?
Fazer o upload na API, é tranquilo para você, certo?
Quer aprender enviar do Vue 3 para o backend (API), isso mesmo?
Ensino isso no LaraChat:
https://github.com/especializati/larachat/blob/main/resources/js/pages/Profile.vue#L106
Ok professor, como estou iniciando em vue estou usando o conceito da aula em que adiciono os dados, dentro desse conceito tenti encaixar o codigo para upload mais não esta pegando o valor da imagem, pode me ajudar?
abaixo todo o codigo
<template>
<div>
<h1>Adicionar Novo produto</h1>
<form action="#" method="post" @submit.prevent="addProduct" enctype="multipart/form-data">
<select name="category_id" v-model="category_id">
<option value="0">Selecione a categoria</option>
<option value="1"> Categoria A</option>
<option value="2"> Categoria B</option>
<option value="3"> Categoria C</option>
<option value="4"> Categoria D</option>
<option value="5"> Categoria E</option>
</select>
<input type="text" name="name" placeholder="Nome" v-model="name">
<input type="text" name="description" placeholder="Descrição" v-model="description">
<input type="file" name="image" placeholder="Imagem" @change="onFileChange">
<button type="submit">Enviar</button>
</form>
</div>
</template>
<script>
import { ref } from 'vue'
import ProductService from '@/services/products.service'
import router from '@/router'
export default {
name: 'addProduct',
setup() {
const category_id = ref('')
const name = ref('')
const description = ref('')
const image = ref('')
function onFileChange() {
let files = e.target.files || e.dataTransfers.files
if(!files.length)
return
this.upload = files[0]
console.log(files.name);
}
const addProduct = () => {
const params = {
category_id: category_id.value,
name: name.value,
description: description.value,
image: image.value,
completed: false,
headers:{
'content-type' : 'multipart/form-data'
}
}
console.log(params);
ProductService.addProduct(params)
.then(() => router.push({name: 'products.index'}))
}
return {
addProduct,
category_id,
name,
description,
image,
onFileChange
}
}
}
</script>
Ajudo sim, claro.
--
Está tendo algum erro? Qual?
--
No método onFileChange, qual o valor de console.log(files.name);?
Na verdade não sei se esta correto o que estou fazendo, gostaria muito que me ajudasse, não existe uma forma de fazermos um call por exemplo pra tirar essa duvida? estou travado há dias nessa questão e isso tem atrasado meu aprendizado, se possivel professor me de esse help, tenho uma outra plataformas de cursos que pago que tem esse recurso e ajuda muito
Fala Renato!
Como vai?
Infelizmente não consigo dar um suporte tão individual assim, é inviável, nem mesmo consultorias estou pegando, por conta da tempo. Mas, fico muito feliz em saber que existem outras plataformas que conseguem prestar esse nível de suporte/consultoria.
--
Sobre o seu problema, estou sempre à disposição para te ajudar, sempre te respondo e responderei todos os dias úteis. Pode contar comigo!
--
Se quiser gravar um vídeo, mostrando o seu projeto, é uma maneira legal de explicar a sua dúvida e abreviar o suporte.
Compartilha o código no GitHub, assim fica mais fácil para mim te ajudar também.
Que pena, seria otimo, porque nem sempre as duvidas são compreendidas por vc e ficamos nesse arranca rabo o que dificulta muito o aprendizado e desanima um pouco tb, mais ok, aqui esta o projeto no Git, espero de coração que possa me ajudar...
https://github.com/renatoribeiromachado/consumirApiVue3
Nele vc vera que tentei enviar a imagem de duas formas, com formData e por params, nenhum dos dois da certo
Detalhe, pelo postman envia corretamente o que significa que a API esta ok
me ajude por favor a entender o porque do formData não carregar a imagem, fico no aguardo pra poder sair dessa etapa
o que quero saber é como inserir alem dos dados a imagens, os dados eu consigo sem problema, minha dificuldade é com imagem, ninguem conseguiu me ajudar nem no grupo do telegram e tb não achei nada na net
Fala Renato!
Da minha parte discordo, que "ficamos nesse arranca rabo", estou sempre tentando ajudar, peço desculpas de não passei essa impressão.
Sobre compreender a dúvida, muitas vezes ela está clara em nossa mente, mas ao transcrever não fica tão claro, porque a outra pessoa não está envolvida no processo, isso é normal, por isso muitas vezes respondo uma dúvida com outras dúvidas.
--
O processo de upload para o PHP é um pouco complexo, digo, no sentido de ter muitos detalhes que o frontend precisa se atentar.
No LaraChat por exemplo, onde mostrei como fazer esse upload, perceba, que tem muitos detalhes bem importantes, como headers necessários:
https://github.com/especializati/larachat/blob/main/resources/js/vuex/modules/me/index.js#L3
Esse header faltou no seu projeto.
O verbo http não pode ser "POST": https://github.com/especializati/larachat/blob/main/resources/js/vuex/modules/me/index.js#L67
---
Como são muitos detalhes, acho uma boa dá uma assistida no módulo 11 do LaraChat, porque nele falo de todas essas particularidades:
https://academy.especializati.com.br/aula/alterar-imagem-perfil-com-vuex
Se não entender a dinâmica, podemos levar o suporte para um próximo nível!
Aguardo você;
Professor Carlos, no link do github que passei anteriormente estou utilizando os headers e não estou fazendo edição e sim cadastro dos campos category_id, name, description e image, achei que iria anakisar meu codigo e mostrar onde errei, estou me baseando nessa aula:
https://academy.especializati.com.br/aula/vue-3-composicao-api-adicionar
aqui vc ensina cadastrar os dados mais não ensina cadastrar imagem e é isso que estou tentando fazer, assistir as outras aulas sem entender como essa funcionaria com cadastro tambem de imagem, esta me atrapalhando mais, ja que estou tentando entender a logica, por favor me de um help, agaurdo retorno
Novamente reforço, estou aqui para te ajudar, não tem a necessidade de perder a postura/paciência...
Você está assistindo uma aula onde ensino a cadastrar sem imagem, e a aula onde falo de todos os pré-requisitos (caminhos) para enviar um arquivo para o backend com Vue.js, chegou a assistir? :-)
https://academy.especializati.com.br/aula/alterar-imagem-perfil-com-vuex
Mais uma que vai te ajudar: https://academy.especializati.com.br/aula/atualizar-background-chat-com-vuex
Sim professor eu assiti, mais não comprendi esse é o problema, por isso enviei o link para que possa analisar de me mostrar onde estou errando, de fato quero muito aprender
Não é possivel fazer um video nessa aula ensinando fazer o upload?
https://academy.especializati.com.br/aula/vue-3-composicao-api-adicionar
Vamos analisar o seu código, se informa um arquivo, o que acontece?
Nada!
https://github.com/renatoribeiromachado/consumirApiVue3/blob/master/src/views/Products/AddProduct.vue#L40
Por que?
Porque faltou fazer algo, tipo isso:
https://github.com/especializati/larachat/blob/main/resources/js/pages/Profile.vue#L111
----
Rodei o seu projeto, e veja o que é enviado para o backend: https://prnt.sc/nBep-6VZTq7R
Nada!
O próprio editor reclama, de onde vem essa variável?!
https://prnt.sc/ODkt_LpoP265
---
Rodei e corrigi todos os bugs, testei e está funcionando, segue a sessão script:
import { ref } from 'vue'
import ProductService from '@/services/products.service'
import router from '@/router'
export default {
name: 'addProduct',
setup() {
const category_id = ref('')
const name = ref('')
const description = ref('')
let imageUpload = null
const onFileChange = (e) => {
let files = e.target.files || e.dataTransfer.files
if (files.length == 0) return
imageUpload = files[0]
}
const addProduct = () => {
const formData = new FormData()
formData.append('category_id', category_id.value);
formData.append('name', name.value);
formData.append('description', description.value);
if (imageUpload !== null)
formData.append('image', imageUpload);
const config = {
headers:{
'content-type': 'multipart/form-data'
}
}
ProductService.addProduct(formData,config)
.then(() => router.push({name: 'products.index'}))
}
return {
addProduct,
category_id,
name,
description,
onFileChange,
FormData
}
}
}
Deu certo professor, muito obrigado, não fique bravo comigo, mais tenho outro grande problema, tentei mais sem sucesso, como faço pra editar essa imagem? alguma dica?
Não fico bravo, jamais! Tenho prazer em ajudar.
--
A edição, basta fazer o replace da imagem no backend, digo, fazer o upload com o mesmo nome de arquivo, se a imagem foi salva com o nome teste.png para alterar a imagem, faça o upload com o nome teste.png
Desculpa novamente professor, mais estou iniciando em Vue, o que estou tentando é editar juntos com os dados, veja meu codigo que não esta funcionando com a edição da imagem:
<template>
<div>
<h1>Editar Product</h1>
<form action="#" method="post" @submit.prevent="editProduct">
<select name="category_id" v-model="product.category_id">
<option value="0">Selecione a categoria</option>
<option value="1"> Categoria A</option>
<option value="2"> Categoria B</option>
<option value="3"> Categoria C</option>
<option value="4"> Categoria D</option>
<option value="5"> Categoria E</option>
</select>
<input type="text" name="name" placeholder="Titulo do produto" v-model="product.name">
<input type="text" name="description" placeholder="Descrição" v-model="product.description">
<input type="file" name="image" ref="fileInput" placeholder="Imagem" @change="onFileChange">
<button type="submit"> Enviar
</button>
</form>
</div>
</template>
<script>
import { onMounted, reactive } from 'vue'
import ProductService from '@/services/products.service'
import router from '@/router'
export default {
name: 'EditProduct',
props: {
id: {
require: true
}
},
setup(props) {
const product = reactive({
category_id: '',
name: '',
description: '',
image: null,
completed: false
})
const onFileChange = (e) => {
let files = e.target.files || e.dataTransfer.files
if (files.length == 0) return
imageUpload = files[0]
}
onMounted(async () => {
product.loading = true
ProductService.getProduct(props.id)
.then(response => {
console.log(response);
const productR = response.data
product.category_id = productR.category_id
product.name = productR.name
product.description = productR.description
product.completed = productR.completed == 'S'
})
})
const editProduct = () => {
if (imageUpload !== null)
formData.append('product.image', imageUpload);
const config = {
headers:{
'content-type': 'multipart/form-data'
}
}
ProductService.editProduct(props.id,config,formData, {...product})
.then(() => router.push({name: 'products.index'}))
}
return {
editProduct,
product,
onFileChange
}
}
}
</script>
OBS: Atualiza o projeto no GitHub, porque fica mais fácil para mim identificar onde você errou.
---
Troca isso:
formData.append('product.image', imageUpload);
Por isso:
formData.append('image', imageUpload);
---
Agora entra um ponto super importante, mesmo sendo uma request PUT ou PATCH, precisa fazer a request como POST, e enviar um param a mais chamado _method=verbo_http_aqui
Tipo isso:
https://github.com/especializati/larachat/blob/main/resources/js/vuex/modules/me/index.js#L67
---
Do lado da API, está tudo certo? Fazendo o replace da imagem certinho né?
ola professor Carlos, obrigado pelo retorno, fiz as alterações que disse, mais ainda sem sucesso
subi as alterações no git, agradeço mais uma vez se puder me ajudar nessa...
https://github.com/renatoribeiromachado/consumirApiVue3
Você fez um if sem as chaves para usar dois trechos, e também sobrou um espaço abaixo:
https://github.com/renatoribeiromachado/consumirApiVue3/blob/master/src/views/Products/EditProduct.vue#L69
// Deixa assim
if (imageUpload !== null) {
formData.append('image', imageUpload)
}
// Qual o valor de imageUpload? print do log por favor
Deixa o _method, lá no service, que NÃO foi atualizado para post (ainda está com put):
static async editProduct(id, formData, config)
{
formData.append('_method', 'PATCH')
return axios.post(`/products/${id}`, formData, config)
}
OBS: O seu formData precisa ter todos os dados do form, igual vc fez no insert.
Precisa ser igual ao exemplo:
https://github.com/especializati/larachat/blob/main/resources/js/vuex/modules/me/index.js#L67
Observe que o método é post, mas com o _method=PATCH
--
Faz essas alterações em diga por favor se deu certo.
professor fiz essas alterações mais sem sucesso
atualizei o codigo no github
https://github.com/renatoribeiromachado/consumirApiVue3
EditProduct.vue
por favor me da mais esse help, ficarei muito agradecido
Resolvido professor Carlos achei os bugs, obrigado, vamos em frente
Precisa estar logado para conseguir responder a este ticket!
Clique Aqui Para Entrar!