Reciba el flujo de archivos pdf devuelto por el backend y use Vue-pdf para realizar la vista previa (paginación) en el front-end

Directorio de artículos de la serie Vue

需求:后端返回文件流前端将文件流转为成blob地址预览pdf文件


提示:以下是本篇文章正文内容,下面案例可供参考

1. Instale las dependencias del complemento PDF

npm instalar vue-pdf --save

2. Encapsule el componente vuePdf como una página de vista previa y salte a la página de vista previa a través del formulario de transferencia de parámetros de enrutamiento Management.vue

1.Vista.de.gestión

El código es el siguiente (ejemplo):

inserte la descripción de la imagen aquí

  • Solicitud encapsulada pdfDocument
  • inserte la descripción de la imagen aquí
  一定要加上
      {
    
    
        responseType: "blob",
      }

El flujo de archivo pdf devuelto en segundo plano es result.data
inserte la descripción de la imagen aquí
con el código:

 // 预览
    async scanSubmit(row) {
    
    
      // 这个代码我不多做解释,接口请求而已
      const result = await pdfDocument(this.fileId);
      // 直接使用createObjectURL可能会出现问题
      // 所以我建议使用下面这种方式将文件流转化为本地blod地址
      var binaryData = [];
      binaryData.push(result.data);
      console.log(binaryData);
      // 记得一定要设置application的类型
      let url = window.URL.createObjectURL(
        new Blob(binaryData, {
    
    
          type: "application/pdf;charset=utf-8",
        })
      );
      if (url != null && url != undefined && url) {
    
    
        // vue路由跳转并以问号形式携带vue-pdf预览时所需要的pdf地址
        const {
    
     href } = this.$router.resolve({
    
    
          path: "/vuePdf",
          query: {
    
    
            //要传的参数
            url: url,
          },
        });
        // 新页面打开
        window.open(href, "_blank");
        this.openTheScanningdialog = false;
      }
    },

2.vuedf.vue

Parte HTML, no es necesario modificar, la copia se puede usar directamente

<template>
  <div id="container">
    <!-- 上一页、下一页 -->
    <div class="right-btn">
      <!-- 输入页码 -->
      <div class="pageNum">
        <input
          v-model.number="currentPage"
          type="number"
          class="inputNumber"
          @input="inputEvent()"
        />
        / {
    
    {
    
     pageCount }}
      </div>
      <div @click="changePdfPage('first')" class="turn">首页</div>
      <!-- 在按钮不符合条件时禁用 -->
      <div
        @click="changePdfPage('pre')"
        class="turn-btn"
        :style="currentPage === 1 ? 'cursor: not-allowed;' : ''"
      >
        上一页
      </div>
      <div
        @click="changePdfPage('next')"
        class="turn-btn"
        :style="currentPage === pageCount ? 'cursor: not-allowed;' : ''"
      >
        下一页
      </div>
      <div @click="changePdfPage('last')" class="turn">尾页</div>
    </div>

    <div class="pdfArea">
      <!-- // 不要改动这里的方法和属性,下次用到复制就直接可以用 -->
      <pdf
        :src="src"
        ref="pdf"
        v-show="loadedRatio === 1"
        :page="currentPage"
        @num-pages="pageCount = $event"
        @progress="loadedRatio = $event"
        @page-loaded="currentPage = $event"
        @loaded="loadPdfHandler"
        @link-clicked="currentPage = $event"
        style="display: inline-block; width: 100%"
        id="pdfID"
      ></pdf>
    </div>
    <!-- 加载未完成时,展示进度条组件并计算进度 -->
    <div class="progress" v-if="loadedRatio != 1">
      <el-progress
        type="circle"
        :width="70"
        color="#53a7ff"
        :percentage="
          Math.floor(loadedRatio * 100) ? Math.floor(loadedRatio * 100) : 0
        "
      ></el-progress>
      <br />
      <!-- 加载提示语 -->
      <span>{
    
    {
    
     remindShow }}</span>
    </div>
  </div>
</template>

Parte JS, no es necesario modificar, la copia se puede usar directamente

<script>
import pdf from "vue-pdf";

export default {
    
    
  components: {
    
    
    pdf,
  },
  data() {
    
    
    return {
    
    
      // ----- loading -----
      remindText: {
    
    
        loading: "加载文件中,文件较大请耐心等待...",
        refresh: "若卡住不动,可刷新页面重新加载...",
      },
      remindShow: "加载文件中,文件较大请耐心等待...",
      intervalID: "",
      // ----- vuepdf -----
      // src静态路径: /static/xxx.pdf
      // src服务器路径: 'http://.../xxx.pdf'
      src: "",
      // 当前页数
      currentPage: 0,
      // 总页数
      pageCount: 0,
      // 加载进度
      loadedRatio: 0,
    };
  },

  created() {
    
    
    // 页面加载,拿到路由中的url复制给data中的src
    this.src = this.$route.query.url;
    console.log(this.src);
  },
  mounted() {
    
    
    // // 更改 loading 文字
    this.intervalID = setInterval(() => {
    
    
      this.remindShow === this.remindText.refresh
        ? (this.remindShow = this.remindText.loading)
        : (this.remindShow = this.remindText.refresh);
    }, 4000);
  },
  methods: {
    
    
    // 页面回到顶部
    toTop() {
    
    
      document.getElementById("container").scrollTop = 0;
    },
    // 输入页码时校验
    inputEvent() {
    
    
      if (this.currentPage > this.pageCount) {
    
    
        // 1. 大于max
        this.currentPage = this.pageCount;
      } else if (this.currentPage < 1) {
    
    
        // 2. 小于min
        this.currentPage = 1;
      }
    },
    // 切换页数
    changePdfPage(val) {
    
    
      if (val === "pre" && this.currentPage > 1) {
    
    
        // 切换后页面回到顶部
        this.currentPage--;
        this.toTop();
      } else if (val === "next" && this.currentPage < this.pageCount) {
    
    
        this.currentPage++;
        this.toTop();
      } else if (val === "first") {
    
    
        this.currentPage = 1;
        this.toTop();
      } else if (val === "last" && this.currentPage < this.pageCount) {
    
    
        this.currentPage = this.pageCount;
        this.toTop();
      }
    },

    // pdf加载时
    loadPdfHandler(e) {
    
    
      // 加载的时候先加载第一页
      this.currentPage = 1;
    },
  },
  destroyed() {
    
    
    // 在页面销毁时记得清空 setInterval
    clearInterval(this.intervalID);
  },
};
</script>

La parte CSS se puede modificar según sus propias necesidades.

<style scoped>
#container {
    
    
  position: absolute !important;
  left: 0;
  right: 0;
  bottom: 0;
  top: 0;
  background: #f4f7fd;
  overflow: auto;
  font-family: PingFang SC;
  width: 100%;
  display: flex;
  /* justify-content: center; */
  position: relative;
}

/* 右侧功能按钮区 */
.right-btn {
    
    
  position: fixed;
  right: 5%;
  bottom: 15%;
  width: 120px;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  z-index: 99;
}

.pdfArea {
    
    
  width: 900px;
  margin: 0 auto;
}

/* ------------------- 输入页码 ------------------- */
.pageNum {
    
    
  margin: 10px 0;
  font-size: 18px;
}

/*在谷歌下移除input[number]的上下箭头*/
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
    
    
  -webkit-appearance: none !important;
  margin: 0;
}

/*在firefox下移除input[number]的上下箭头*/
input[type="number"] {
    
    
  -moz-appearance: textfield;
}

.inputNumber {
    
    
  border-radius: 8px;
  border: 1px solid #999999;
  height: 35px;
  font-size: 18px;
  width: 60px;
  text-align: center;
}

.inputNumber:focus {
    
    
  border: 1px solid #00aeff;
  background-color: rgba(18, 163, 230, 0.096);
  outline: none;
  transition: 0.2s;
}

/* ------------------- 切换页码 ------------------- */
.turn {
    
    
  background-color: #164fcc;
  opacity: 0.9;
  color: #ffffff;
  height: 70px;
  width: 70px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 5px 0;
}

.turn-btn {
    
    
  background-color: #164fcc;
  opacity: 0.9;
  color: #ffffff;
  height: 70px;
  width: 70px;
  border-radius: 50%;
  margin: 5px 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.turn-btn:hover,
.turn:hover {
    
    
  transition: 0.3s;
  opacity: 0.5;
  cursor: pointer;
}

/* ------------------- 进度条 ------------------- */
.progress {
    
    
  position: absolute;
  right: 50%;
  top: 50%;
  text-align: center;
}

.progress > span {
    
    
  color: #199edb;
  font-size: 14px;
}
</style>

representaciones

inserte la descripción de la imagen aquí

**

Realizar descarga/abrir en línea

**

①Instalar downloadjs

npm install downloadjs

②Introducir donde sea necesario

import download from 'downloadjs'

③La descarga se puede realizar llamando a descargar en el método de descarga

inserte la descripción de la imagen aquí
El nombre del tipo de archivo de guardado de datos de flujo de archivo para descargar

Supongo que te gusta

Origin blog.csdn.net/WuqibuHuan/article/details/125312994
Recomendado
Clasificación