Vue3 implements file preview in Word, Excel, PDF, pictures, videos and other formats!!!!

First the renderings

Plug-in installation

First let’s talk about the word file which is the docx-preview plug-in

The excel file uses the xlsx plug-in

Introducing the data returned by the backend

Because the data is processed at the interceptor, the data you finally get when calling the interface is an object, which contains:

url: Temporary link converted from blob object to access Blob data. This link can be used to display binary data in a web page, such as displaying images or playing audio and video files.

blobs: The returned Blob object represents the binary data obtained from the network request.

The upper and lower parts are very important!!!!!!!!

If the returned format is in a normal format, we can convert it directly.

  1. const blob = new Blob([res], { type: ‘application/pdf’ }) //Convert the type you need into a blob object

  2. const url = window.URL.createObjectURL(blob) //Convert object into link

That is, the data returned when you disconnect the interface later

Print it for everyone. When I was searching for this kind of information on the Internet, I got confused in this part. I didn’t understand the data format.

Then it’s time to officially write it.

Download the imported plug-in (I am importing the v3 version into vue2. Search the csdn official website for vue preview files. There are a lot of them. Search for them yourself)

//word document comments
import { renderAsync } from 'docx-preview';
//excel annotation
import * as XLSX from "xlsx";

Word Preview

I don’t know the result. Swipe up to return the content. What is passed here is the blob object!!

 <!-- If the data number is displayed in the word document format, I will add my own defined type to determine the fileType. You can delete it -->
  <div ref="refWord" id="fileShow" v-else-if="fileType == 'docx'" style="width: 100%;height: 100%;" ></div>


     //js code department
     const previewContainer = document.getElementById('fileShow');
            renderAsync(result.blob, previewContainer) //Rendering

Excel preview

I don’t know the result. Swipe up to return the content. What is passed here is the blob object!! The middle content is the plug-in data processing when getting the data to render. Finally, the processed data is passed as a parameter to the method of processing the style.

<!-- If the data is displayed in excel format -->
<div id="fileShowTwo" style="width: 100%;height: 100%;" v-else-if="fileType == 'xlsx'">
        <div class="tab">
        <el-radio-group size="small" v-model="excel.sheetNameActive" @change="getSheetNameTable">
            <el-radio-button v-for="(item, index) in excel.sheetNames" :key="index" :label="item"></el-radio-button>
        </el-radio-group>
        </div>
        <div
            style="margin-top: 5px;border: 1px solid #a0a0a0;overflow:auto;">
        <div v-html="excel.SheetActiveTable" style="padding: 10px 15px"></div>
        </div>
</div>
<div v-else-if="fileType == 'mp4'" style="width: 100%;height: 100%;">
    <video :src="fileAddress" controls style="width: 100%;height: 100%;"></video>
</div>

//js code department

//Data definition required for table preview
const data = reactive({
    excel: {
        // data
        workbook: {},
        //Collection of table names
        sheetNames: [],
        //Activate items
        sheetNameActive: "",
        //Currently active form
        SheetActiveTable: ""
    }
})
const { excel } = toRefs(data);
// Data required for video preview
const emptyTips = ref('No content yet');



      //The content written in the method when the format is excel
            const reader = new FileReader(); //Created a FileReader object, which is used to read file content asynchronously
            //Convert blob to ArrayBuffer object through readAsArrayBuffer
            reader.readAsArrayBuffer(result.blob) // res.data here is a blob file stream
            reader.onload = (event) => {
                // Read ArrayBuffer data into Uint8Array
                var data = new Uint8Array(event.target.result);
                //The type in the data here must correspond to the type type behind it.
                var workbook = XLSX.read(data, { type: "array" });
                const sheetNames = workbook.SheetNames // Collection of worksheet names
                excel.value.workbook = workbook
                excel.value.sheetNames = sheetNames
                excel.value.sheetNameActive = sheetNames[0]
                //method
                getSheetNameTable(sheetNames[0])
            };



//method defined
const getSheetNameTable = (sheetName) => {
      try {
        // Get the data of the current worksheet
        const worksheet = excel.value.workbook.Sheets[sheetName]
        // Convert to data 1. There are some problems with the json data. 2. If it is html, the style needs to be modified.
        let htmlData = XLSX.utils.sheet_to_html(worksheet, { header: '', footer: '' })
        htmlData = htmlData === '' ? htmlData : htmlData.replace(/<table/, '<table class="default-table" border="1px solid #ccc" cellpadding="0 " cellspacing="0"')
        //The first line changes the color
        htmlData = htmlData === '' ? htmlData : htmlData.replace(/<tr/, '<tr style="background:#b4c9e8"')
        excel.value.SheetActiveTable = htmlData
    } catch (e) {
        //If there is no data in the worksheet, go here to process it
        excel.value.SheetActiveTable = '<h4 style="text-align: center">' + emptyTips.value + '</h4>'
    }
}

pdf preview

This requires the use of iframe tags. The type of the blob object needs to be “type”: “application/pdf”. You can take a look at your own blob object. If the backend returns directly the blob format but the type is wrong, wait. The code below is converted. If the returned ordinary data is converted, you can set the type yourself when converting the blob object according to the above format.

 <!-- If it is pdf data display -->
     <iframe :src="fileAddress" type="application/pdf" v-else-if="fileType == 'pdf'" id="pdfShow" width="100% " height="100%"></iframe>



//js code department
  //When the format is pdf
             const reader = new FileReader();
            reader.readAsArrayBuffer(result.blob);
            reader.onload = function () {
                fileAddress.value = URL.createObjectURL(new Blob([reader.result], { "type": "application/pdf" }))
            }

The last is jpg png, mp4 format preview

 //The link for blob object conversion is used here. Pay attention to the distinction!!
if (type == 'jpg' || type == 'png' || type == 'mp4') {
            fileAddress.value = result.url
}


//Image type display
 <img style="width: 150px;height: 150px;" :src="fileAddress" alt="" v-if="fileType == 'jpg' || fileType == \ 'png'">

//Video type display
  <div v-else-if="fileType == 'mp4'" style="width: 100%;height: 100%;">
           <video :src="fileAddress" controls style="width: 100%;height: 100%;"></video>
    </div>

Download file!!

<el-button @click="DownloadFn()"> Download</el-button>


// Download Document
const DownloadFn = () => {
    let a = document.createElement('a')
     // Download link
    a.href = blobUploadValue.value //This is the blob link!!
    //Download file name, if the backend does not return, you can write a.download = 'file.pdf'
    //Here is the name of the file you uploaded plus its type jpg, png, docx....
    a.download = fileNameValue.value + '.' + fileType.value
    document.body.appendChild(a)
    // Click the a tag to download
    a.click()
    // remove element
    document.body.removeChild(a)
}

Finally the complete code

<el-dialog v-model="dialogTabsVisible" title="Attachment display" class="file-show-box" @close="closeDialog()">
            <div class="file-body">
                <!-- Attachment list on the left -->
                <div class="file-left" >
                    <div class="list" :class="{'list-active' : listAct == index}" v-for="(item, index) in fileList" :key=" index" @click="handleClick(item,index)">{<!-- -->{ item.name }}</div>
                </div>
                <div class="file-right">
                    <div class="downFile" v-if="fileType != 'pdf'">
                            <el-button @click="DownloadFn()"> Download</el-button>
                    </div>
                    <!-- If it is image data display -->
                    <img style="width: 150px;height: 150px;" :src="fileAddress" alt="" v-if="fileType == 'jpg' || fileType == \ 'png'">
                    <!-- If the data is displayed in txt format -->
                    <iframe :src="fileAddress" frameborder="0" v-else-if="fileType == 'txt'" style="width: 90%; height: 100%;\ "></iframe>
                    <!-- If it is pdf data display -->
                    <iframe :src="fileAddress" type="application/pdf" v-else-if="fileType == 'pdf'" id="pdfShow" width="100% " height="100%"></iframe>
                    <!-- If the data number is displayed in word document format -->
                    <div ref="refWord" id="fileShow" v-else-if="fileType == 'docx'" style="width: 100%;height: 100%;" ></div>
                    <!-- If the data is displayed in excel format -->
                    <div id="fileShowTwo" style="width: 100%;height: 100%;" v-else-if="fileType == 'xlsx'">
                           <div class="tab">
                            <el-radio-group size="small" v-model="excel.sheetNameActive" @change="getSheetNameTable">
                                <el-radio-button v-for="(item, index) in excel.sheetNames" :key="index" :label="item"></el-radio-button>
                            </el-radio-group>
                            </div>
                            <div
                                style="margin-top: 5px;border: 1px solid #a0a0a0;overflow:auto;">
                            <div v-html="excel.SheetActiveTable" style="padding: 10px 15px"></div>
                            </div>
                    </div>
                    <div v-else-if="fileType == 'mp4'" style="width: 100%;height: 100%;">
                        <video :src="fileAddress" controls style="width: 100%;height: 100%;"></video>
                    </div>
                    <div v-else>
                            This file does not support preview, please download and view
                    </div>
                </div>
            </div>
        </el-dialog>




//js part

//Data required for table preview
const data = reactive({
    excel: {
        // data
        workbook: {},
        //Collection of table names
        sheetNames: [],
        //Activate items
        sheetNameActive: "",
        //Currently active form
        SheetActiveTable: ""
    }
})
const { excel } = toRefs(data);
// Data required for video preview
const emptyTips = ref('No content yet');
// download file
// file address
const fileAddress = ref('')
// Download streaming data
const blobUploadValue = ref('')

//The parameter type here is passed from other places. Pay attention to screening.
const downloadFn = (id, type) => {
    let params = { fileId: id }
    download(params).then(result => {
        console.log(result.url, 'resolve');
        console.log(result.blob, 'blob');
         blobUploadValue.value = result.url
        if (type == 'jpg' || type == 'png' || type == 'mp4') {
            //When the format is picture video
            fileAddress.value = result.url
        } else if (type == 'docx') {
            //When the format is word
            const previewContainer = document.getElementById('fileShow');
            renderAsync(result.blob, previewContainer) //Rendering
        } else if (type == 'xlsx') {
            //When the format is excel
            const reader = new FileReader();
            //Convert blob to ArrayBuffer object through readAsArrayBuffer
            reader.readAsArrayBuffer(result.blob) // res.data here is a blob file stream
            reader.onload = (event) => {
                // Read ArrayBuffer data into Uint8Array
                var data = new Uint8Array(event.target.result);
                //The type in the data here must correspond to the type type behind it.
                var workbook = XLSX.read(data, { type: "array" });
                const sheetNames = workbook.SheetNames // Collection of worksheet names
                excel.value.workbook = workbook
                excel.value.sheetNames = sheetNames
                excel.value.sheetNameActive = sheetNames[0]
                getSheetNameTable(sheetNames[0])
            };
        } else if (type == 'pdf') {
            //When the format is pdf
             const reader = new FileReader();
            reader.readAsArrayBuffer(result.blob);
            reader.onload = function () {
                fileAddress.value = URL.createObjectURL(new Blob([reader.result], { "type": "application/pdf" }))
            }
        }
    })
}

// Download Document
const DownloadFn = () => {
    let a = document.createElement('a')
     // Download link
    a.href = blobUploadValue.value
    //Download file name, if the backend does not return, you can write a.download = 'file.pdf'
    a.download = fileNameValue.value + '.' + fileType.value
    document.body.appendChild(a)
    // Click the a tag to download
    a.click()
    // remove element
    document.body.removeChild(a)
}

const getSheetNameTable = (sheetName) => {
      try {
        // Get the data of the current worksheet
        const worksheet = excel.value.workbook.Sheets[sheetName]
        // Convert to data 1. There are some problems with the json data. 2. If it is html, the style needs to be modified.
        let htmlData = XLSX.utils.sheet_to_html(worksheet, { header: '', footer: '' })
        htmlData = htmlData === '' ? htmlData : htmlData.replace(/<table/, '<table class="default-table" border="1px solid #ccc" cellpadding="0 " cellspacing="0"')
        //The first line changes the color
        htmlData = htmlData === '' ? htmlData : htmlData.replace(/<tr/, '<tr style="background:#b4c9e8"')
        excel.value.SheetActiveTable = htmlData
    } catch (e) {
        //If there is no data in the worksheet, go here to process it
        excel.value.SheetActiveTable = '<h4 style="text-align: center">' + emptyTips.value + '</h4>'
    }
}










Here is the backend returning a list of attachment names. I render it to the attachment list on the left and then display different file previews on the right by selecting different attachments. I also get it from here, and then I click on the different attachment lists. Execute the above preview method to obtain different blob data and then display it

I can only tell you my logic. After all, everyone’s code is different and may not be directly copied. I still hope it can help you.

Finally paste the renderings