Subida de imágenes en v-md-editor con Vue 3 y Spring Boot

Visión general

v-md-editor es un componente de edición Markdown para Vue que funciona tanto en Vue 2 como en Vue 3. Para incorporar la subida de imágenes es necesario implementar un endpoint en el servidor y manejar el evento upload-image desde el cliente.

Endpoint en el servidor

El siguiente controlador de Spring Boot recibe el archivo, lo almacena en disco y devuelve la URL pública resultante:

@RestController
@RequestMapping("/recursos")
public class RecursoController {

    @PostMapping("/imagen")
    public Resultado<String> guardarImagen(
            @RequestParam("archivo") MultipartFile archivo,
            @RequestParam(value = "ruta", required = false) String ruta) {

        String urlPublica = almacenarArchivo(archivo, ruta);
        return Resultado.ok(urlPublica, "Imagen guardada correctamente");
    }
}

Ejemplo de respuesta exitosa:

{
  "codigo": 200,
  "mensaje": "Imagen guardada correctamente",
  "datos": "http://127.0.0.1:9005/recursos/ae83c411083848a69efccf7094183348.png"
}

Componente Vue

En el template se habilita el menú de subida local pasando un array vacío a disabled-menus y se escucha el evento upload-image:

<template>
  <div class="editor-markdown">
    <v-md-editor
      v-model="texto"
      mode="edit"
      height="400px"
      :disabled-menus="[]"
      @upload-image="procesarImagen"
    />

    <v-md-editor v-model="texto" mode="preview" />
  </div>
</template>

<script setup lang="ts">
import { ref } from "vue";
import { ElMessage } from "element-plus";
import { subirImagen } from "@/services/imagenService";

const texto = ref("Introduce el contenido aquí");

const procesarImagen = (evento: any, insertarImagen: any, archivos: File[]) => {
  if (!archivos || archivos.length === 0) return;

  const payload = new FormData();
  payload.append("archivo", archivos[0]);

  subirImagen(payload)
    .then((respuesta) => {
      if (respuesta.codigo === 200 && respuesta.datos) {
        insertarImagen({ url: respuesta.datos });
      } else {
        ElMessage.warning(respuesta.mensaje || "No se pudo subir la imagen");
      }
    })
    .catch(() => ElMessage.error("Fallo la subida de la imagen"));
};
</script>

El servicio que envía el FormData mediante Axios puede verse así:

import axios from "@/utils/peticion";

export function subirImagen(formData: FormData) {
  return axios.post("/recursos/imagen", formData, {
    headers: { "Content-Type": "multipart/form-data" }
  });
}

El objeto FormData permite empaquetar el archivo como multipart/form-data, de modo que el backend pueda recibirlo con MultipartFile. Una vez obtenida la URL, se invoca insertarImagen para renderizar la imagan en el editor.

Propiedades más útiles

  • text: cadena Markdown que se quiere previsualizar.
  • v-model: enlace bidirectional con el contenido.
  • mode: modo de visualización. Valores: edit, editable, preview.
  • default-fullscreen: indica si se activa pantalla completa por defecto.
  • disabled-menus: menús deshabilitados. Dejar vacío para permitir la subida local de imágenes.

Etiquetas: v-md-editor Vue 3 Spring Boot markdown image-upload

Publicado el 9-28 16:26