Tengo un formulario en Vue para cargar una publicación de blog que tiene áreas para título, cuerpo, descripción, fragmento y foto. Todos son obligatorios. Configuré una API en Express para manejar esto, la probé en Postman y funciona, pero no puedo averiguar cómo enviar los archivos a la base de datos desde el navegador. Sigo recibiendo un error 500 e imprimí los datos en la consola y el campo de la foto es nulo, así que estoy seguro de que ese es el problema, pero no puedo resolverlo.

Este es mi formulario en la parte delantera:

<template>
  <div class="container">
    <div id="nav">
      <adminnav/>
    </div>
    <div id="create">
      <h1>Create new post</h1>
    </div>
    <div id="post">
      <body>
        <form>
          <label for="title">Title: </label>
          <textarea v-model=formdata.title rows="5" cols="60" name="title"
            placeholder="Enter text">
          </textarea>
          <br/>
          <label for="body">Body: </label>
          <textarea v-model=formdata.body rows="5" cols="60" name="body"
            placeholder="Enter text">
          </textarea>
          <br/>
          <label for="description">Description: </label>
          <textarea v-model=formdata.description rows="5" cols="60" name="description"
            placeholder="Enter text">
          </textarea>
          <br/>
          <label for="snippet">Snippet: </label>
          <textarea v-model=formdata.snippet rows="5" cols="60" name="snippet"
            placeholder="Enter text">
          </textarea>
          <br/>
          <label for="file">Upload photo: </label>
          <input
            class="form-control-file"
            type="file"
            accept="image/*"
            v-bind="formdata.photo"
          />
          <br/>
          <input id="submit" type="submit" value="submit" @click.prevent="createPost()"/>
        </form>
      </body>
    </div>
  </div>
</template>

<script>
import adminnav from '../components/adminnav.vue';
import PostService from '../service/PostService';

export default {
  name: 'createStory',
  components: {
    adminnav,
  },
  data() {
    return {
      formdata: {
        title: '',
        body: '',
        description: '',
        snippet: '',
        photo: null,
      },
    };
  },
  methods: {
    createPost() {
      console.log(this.formdata);
      /* eslint prefer-destructuring: 0 */
      const formdata = this.formdata;
      PostService.createPost(formdata)
        .then(() => {
          console.log('success');
        });
    },
  },
};
</script>

Esta es la solicitud POST.

router.post("/add-story", upload.single('photo'), async(req, res) => {
  try{
    let post = new Post();
    post.title = req.body.title;
    post.description = req.body.description;
    post.photo = req.file.location;
    post.body = req.body.body;
    post.snippet = req.body.snippet;

    await post.save();
    
    res.json({
      status: true,
      message: "Successfully saved."
    });
    
  } catch(err) {
    res.status(500).json({
      success: false,
      message: err.message
    });
  }
});
0
mike 22 ene. 2021 a las 01:36

1 respuesta

La mejor respuesta

Supervisemos el evento change del archivo <input>. Esto asegura que cada vez que el comportamiento de carga de sus usuarios active el método updatePhoto y almacene los datos del archivo en this.photo.

<input type="file" accept="image/*" class="form-control-file"
    @change="updatePhoto($event.target.name, $event.target.files)"
>

Código para recopilar todos los datos y enviar la solicitud

// Other parts of your vue component
data () {
    return {
        title: '',
        body: '',
        description: '',
        snippet: '',
        photo: {} // To store file data
    };
},
methods: {
    updatePhoto (files) {
        if (!files.length) return;

        // Store the file data
        this.photo = {
            name: files[0].name,
            data: files[0]
        };
    },
    createPost() {
        let formData = new FormData();

        formData.append('title', this.title);
        formData.append('body', this.body);
        formData.append('description', this.description);
        formData.append('snippet', this.snippet);
        formData.append('photo', this.photo.data, this.photo.name);

        PostService.createPost(formdata)
        .then(() => {
            console.log('success');
        });
    }
}
// Other parts of your vue component

Obviamente, me salté muchas cosas, como la estructura completa del componente vue, que creo que no está relacionada con esta pregunta y algunas verificaciones necesarias para asegurarme de que haya un archivo de datos disponible antes de lanzar la solicitud, etc. datos de archivo, así que espero que esta respuesta te inspire.

1
noob 21 ene. 2021 a las 23:06