Solution for online preview of files in uni app

Keywords: Java iOS Vue Android socket

Just passed, I also wish you all good health, everything goes well and no more bugs in your future life.

I. Preface

I wrote an article about uploading directory file: Solution of directory file upload (not only pictures and videos) in uni app system , this time to solve the file preview problem.

  uni-app It is a framework that uses Vue.js to develop all front-end applications. Developers write a set of code that can be distributed to multiple platforms such as iOS, Android, H5, and various small programs (WeChat / Alipay / Baidu / headband /QQ/ pins). When doing business system, it is inevitable to meet the demand of file online preview. The files here include PDF, Word, Excel, PPT, pictures, etc. Online preview is not to open the preview with local software or browser after downloading, but to view it directly in the form of file stream. This scheme mainly solves the problem of online preview and a series of problems encountered in the development of uni app.

                       

First of all, we will think of pdf preview. First of all, we will think of pdf preview in the front end. pdf.js , then we will pdf.js Speaking of it.

II. PDF Preview

pdf.js open source address and online example
Github
Online Demo

2.1 use method 1

<img src="https://user-gold-cdn.xitu.io...;h=288&f=png&s=32729" width="240" align=center />

<img src="https://user-gold-cdn.xitu.io...;h=262&f=png&s=17092" width="240" align=center />

  • New Vue component file-preview.vue

    • viewerUrl: front end local viewer.html page address
    • fileUrl: file stream access address, refer to "3. File stream service"
<template>
    <view>
        <web-view :src="allUrl"></web-view>
    </view>
</template>

<script>
    import globalConfig from '@/config'
    export default {
        data() {
            return {
                viewerUrl: '/hybrid/html/web/viewer.html',
                // viewerUrl: globalConfig.baseUrl + '/pdf/web/viewer.html',
                allUrl: ''
            }
        },
        onLoad(options) {
            let fileUrl = encodeURIComponent(
                globalConfig.baseUrl + '/api/attachment?name=' + options.name + '&url=' + options.url)
            this.allUrl = this.viewerUrl + '?file=' + fileUrl
        }
    }
</script>
  • Effect

    • h5 terminal

Display normal

  • Android terminal

The display is fuzzy, and the Chinese display is incomplete, in which the fuzzy problem is the cause of the simulator; but the Chinese display problem is true, and there are two warnings in debugging. The second warning pdf.js does not display the electronic signature (digital signature) by default. After checking a lot of data, it has not been solved. Have you ever met and solved it?
<img src="https://user-gold-cdn.xitu.io...;h=812&f=png&s=253098" width="360" align=center />

  • iOS terminal

Cross domain issues and debugging failure to access pdf.js internationalization file
<img src="https://user-gold-cdn.xitu.io...;h=452&f=png&s=95345" width="360" align=center />

  • Solve

Based on the problems of Android and iOS preview, the most fundamental reason is that the viewer.html file is put on the front end, resulting in the loss of the loaded resource file. To solve this problem, I was wondering if I could directly put it on the spring backend as a static resource access file. So here's how.

2.2 method 2

  • In the back-end code based on spring mvc, put the build and web folders of plug-in package under webapp (New pdf folder), and the back-end projects of spring boot architecture are put into the static resource directory in the same way.

<img src="https://user-gold-cdn.xitu.io...;h=650&f=png&s=69156" width="400" align=center />

  • Configuring static file access in xml files

  • Modify the viewerUrl in the front-end component file-preview.vue, where globalConfig.baseUrl is the baseUrl of the proxy back-end address. For example, proxyTable or nginx agent in Vue
viewerUrl: globalConfig.baseUrl + '/pdf/web/viewer.html'
  • Effect after modification

    • iOS terminal

<img src="https://user-gold-cdn.xitu.io...;h=698&f=png&s=184270" width="360" align=center />

  • Android terminal

Fuzziness is the cause of the simulator, and it passes the test on the real machine.
<img src="https://user-gold-cdn.xitu.io...;h=634&f=png&s=140599" width="360" align=center />

III. file flow service

3.1 method 1: tomcat configuration

Configure server.xml under tomcat's config directory, and add the following in the middle of the last < server > < server >.

port=8090 file access service port
docBase="/root /" file storage directory
The files on the server will be stored in the directory / root/fileData /
The file access address is: http://ip address: 8090/fileData /...

<Service name="fileData">  
    <!--Assign port 8089 -->  
    <!-- <Connector port="8090" protocol="HTTP/1.1" connectionTimeout="20000" URIEncoding="GBK" redirectPort="8443" /> -->
    <Connector port="8090" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
    <Engine name="fileData" defaultHost="localhost">  
    <!--name For project access address this configured access is http://localhost:8080 appBase configures the path under wabapps under tomcat -- >     
    <Host name="localhost" appBase="webapps"  
        unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">  
        <!--Resource address-->  
        <Context path="" docBase="/root/" debug="0" reloadable="false"/>  
    </Host>  
    </Engine>
</Service>

3.2 method 2: write code to obtain server file for conversion

Direct code

Read directory file, convert to binary stream
The fileUrl in the front-end component file-preview.vue is / api/attachment

Core code

ios = new FileInputStream(sourceFile);
os = response.getOutputStream();
int read = 0;
byte[] buffer = new byte[1024 * 1024];
while ((read = ios.read(buffer)) != -1) {
    os.write(buffer, 0, read);
}
os.flush();

Complete code

@RequestMapping(value = "/api/attachment", method = RequestMethod.GET)
    public void getFileBytes(@RequestParam("name") String name, @RequestParam("url") String url, HttpServletRequest request, HttpServletResponse response) {
        response.reset();
        response.setContentType("application/octet-stream");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + name);

        AttachmentVO attachmentVO = new AttachmentVO();
        FileInputStream ios = null;
        OutputStream os = null;
        try {
            name = CharsetUtils.toUTF_8(name);
            url = CharsetUtils.toUTF_8(url);

            attachmentVO.setUrl(url);
            attachmentVO.setName(name);
            File sourceFile = getDictionaryFile(attachmentVO, request);
            if (null == sourceFile) {
//                throw new HttpResponseException(300, "attachment does not exist! "";
                return;
            }

            /**
             * Judge document type
             */
            /* Get file name suffix */
            String ext = "";
            if (!"".equals(url) && url.contains(".")) {
                ext = url.substring(url.lastIndexOf(".") + 1, url.length()).toUpperCase();
            }
            /* Preview according to different file types */
            /* Preview pdf */
            if ("PDF".equals(ext)) {
                response.setContentType("application/pdf");
            }

            /**
             * Write the file to the output stream and display it on the interface to achieve preview effect
             */
            ios = new FileInputStream(sourceFile);
            os = response.getOutputStream();
            int read = 0;
            byte[] buffer = new byte[1024 * 1024];
            while ((read = ios.read(buffer)) != -1) {
                os.write(buffer, 0, read);
            }
            os.flush();
        } catch (Exception e) {
            e.printStackTrace();
            try {
                if (null != ios) {
                    ios.close();
                }
                if (null != os) {
                    os.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

IV. preview of office documents (Word, Excel, PPT)

Principle:
Build the OpenOffice service, convert the file to PDF, and preview it with pdf.js.

4.1 build openOffice service

tar xzvfm Apache_OpenOffice_xxx.tar.gz
cd zh-CN/RPMS
rpm -ivh *rpm
  • Function
# 127.0.0.1 the service can only be used locally
/opt/openoffice4/program/soffice "-accept=socket,host=127.0.0.1,port=8100;urp;" -headless -nofirststartwizard &
# 0.0.0.0 remote ip can use
/opt/openoffice4/program/soffice "-accept=socket,host=0.0.0.0,port=8100;urp;" -headless -nofirststartwizard &

4.2 integrated java

  • Add jar package in pom.xml
<!-- openoffice start -->
<dependency>
    <groupId>org.openoffice</groupId>
    <artifactId>juh</artifactId>
    <version>4.1.2</version>
</dependency>
<dependency>
    <groupId>org.openoffice</groupId>
    <artifactId>jurt</artifactId>
    <version>4.1.2</version>
</dependency>
<dependency>
    <groupId>org.openoffice</groupId>
    <artifactId>ridl</artifactId>
    <version>4.1.2</version>
</dependency>
<dependency>
    <groupId>org.openoffice</groupId>
    <artifactId>unoil</artifactId>
    <version>4.1.2</version>
</dependency>
<dependency>
    <groupId>com.artofsolving</groupId>
    <artifactId>jodconverter</artifactId>
    <version>2.2.2</version>
</dependency>
<!-- openoffice end -->

< span style = "color: Red" > note < / span >: jodconverter You need to download version 2.2.2 separately. None of the previous versions works, and there is no version 2.2.2 in maven central warehouse. Then import separately. Download address: https://sourceforge.net/proje...

Separate import

mvn install:install-file -Dfile="jodconverter-2.2.2.jar" -DgroupId=com.artofsolving -DartifactId=jodconverter -Dversion=2.2.2 -Dpackaging=jar
  • Conversion code

Core code

connection = new SocketOpenOfficeConnection(openofficeHost, openofficePort);
connection.connect();
DocumentConverter converter = new StreamOpenOfficeDocumentConverter(connection);
converter.convert(sourceFile, pdfFile);

Complete code

/* Use openOffice to convert office files to pdf format, and preview doc, docx, xls, xlsx, ppt, pptx */
if ("DOC".equals(ext) || "DOCX".equals(ext) || "XLS".equals(ext) || "XLSX".equals(ext) || "PPT".equals(ext) || "PPTX".equals(ext)) {
    /* filePath There is no file suffix in the database. Because the jodConverter must recognize the suffix, rename the file in the server to the file with suffix. */
    // File docfilewithext = new file (filepath + ". + ext.tolowercase()); / / file with suffix
    // docFile.renameTo(docFileWithExt);
    /* Converted filename */
    String filePath = sourceFile.getPath();
    File pdfFile;
    if (filePath.contains(".")) {
        pdfFile = new File(filePath.substring(0, filePath.lastIndexOf(".")) + ".pdf");
    } else {
        pdfFile = new File(filePath + ".pdf");
    }

    /* Determine whether the file to be converted actually exists */
    if (sourceFile.exists()) {
        /* Determine whether the file has been converted. If it has been converted, preview it directly. */
        if (!pdfFile.exists()) {
            OpenOfficeConnection connection;
            /* Open OpenOffice connection */
            try {
                connection = new SocketOpenOfficeConnection(openofficeHost, openofficePort);
                connection.connect();
            } catch (java.net.ConnectException e) {
                log.warn("openOffice Not connected, reconnecting...");

                // Start services for OpenOffice
                String command = openofficeInstallPath + "program/soffice -headless -accept=\"socket,host=127.0.0.1,port=8100;urp;\" -nofirststartwizard";
                Runtime.getRuntime().exec(command);

                Thread.sleep(1000);

                connection = new SocketOpenOfficeConnection(8100);
                connection.connect();

                log.warn("openOffice Reconnect successful!!!");
            }

            try {
                // DocumentConverter converter = new OpenOfficeDocumentConverter(connection);
                DocumentConverter converter = new StreamOpenOfficeDocumentConverter(connection);
                converter.convert(sourceFile, pdfFile);
                connection.disconnect();

//                            Filepath = pdnfile. Getpath(); / / path after file conversion
                sourceFile = pdfFile;
                response.setContentType("application/pdf");
            } catch (OpenOfficeException e) {
                e.printStackTrace(); // Failed to read conversion file
                log.info("Failed to read conversion file!!!");
                return;
            } finally { // When exception occurs, the connection will not be automatically cut off, and the program will be hung all the time.
                try {
                    if (connection != null) {
                        connection.disconnect();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } else {
//                        filePath = pdfFile.getPath(); / / the file has been converted
            sourceFile = pdfFile;
            response.setContentType("application/pdf");
        }
    } else {
        log.info("The document to be previewed does not exist on the server!!!");
        // File does not exist, return directly
        return;
    }
}

V. picture preview

5.1 back end file flow

/* preview pictures */
if ("PNG".equals(ext) || "JPEG".equals(ext) || "JPG".equals(ext)) {
    response.setContentType("image/jpeg");
}
/* Preview files in BMP format */
if ("BMP".equals(ext)) {
    response.setContentType("image/bmp");
}
/* Preview files in GIF format */
if ("GIF".equals(ext)) {
    response.setContentType("image/gif");
}

5.2 front end Preview

Using uni app uni.previewImage Interface
fileUrl: access address for the file stream

// preview pictures
uni.previewImage({
  urls: [fileUrl],
  longPressActions: {
    itemList: ['Send to friends', 'Save pictures', 'Collection'],
    success: function(data) {
      console.log('Selected the first' + (data.tapIndex + 1) + 'Button,The first' + (data.index + 1) + 'Zhang picture');
    },
    fail: function(err) {
      console.log(err.errMsg);
    }
  }
})

Attachment: complete file flow code

@RequestMapping(value = "/api/attachment", method = RequestMethod.GET)
public void getFileBytes(@RequestParam("name") String name, @RequestParam("url") String url, HttpServletRequest request, HttpServletResponse response) {
    response.reset();
    // Fix IFrame reject, invalid
//        response.setHeader("X-Frame-Options", "SAMEORIGIN");
    response.setContentType("application/octet-stream");
    response.setCharacterEncoding("utf-8");
    response.setHeader("Content-Disposition", "attachment;filename=" + name);

    AttachmentVO attachmentVO = new AttachmentVO();
    FileInputStream ios = null;
    OutputStream os = null;
    try {
        name = CharsetUtils.toUTF_8(name);
        url = CharsetUtils.toUTF_8(url);

        attachmentVO.setUrl(url);
        attachmentVO.setName(name);
        File sourceFile = getDictionaryFile(attachmentVO, request);
        if (null == sourceFile) {
//                throw new HttpResponseException(300, "attachment does not exist! "";
            return;
        }

        /**
          * Judge document type
          */
        /* Get file name suffix */
        String ext = "";
        if (!"".equals(url) && url.contains(".")) {
            ext = url.substring(url.lastIndexOf(".") + 1, url.length()).toUpperCase();
        }
        /* Preview according to different file types */
        /* preview pictures */
        if ("PNG".equals(ext) || "JPEG".equals(ext) || "JPG".equals(ext)) {
            response.setContentType("image/jpeg");
        }
        /* Preview files in BMP format */
        if ("BMP".equals(ext)) {
            response.setContentType("image/bmp");
        }
        /* Preview files in GIF format */
        if ("GIF".equals(ext)) {
            response.setContentType("image/gif");
        }
        /* Preview pdf */
        if ("PDF".equals(ext)) {
            response.setContentType("application/pdf");
        }

        /* Use openOffice to convert office files to pdf format, and preview doc, docx, xls, xlsx, ppt, pptx */
        if ("DOC".equals(ext) || "DOCX".equals(ext) || "XLS".equals(ext) || "XLSX".equals(ext) || "PPT".equals(ext) || "PPTX".equals(ext)) {
            /* filePath There is no file suffix in the database. Because the jodConverter must recognize the suffix, rename the file in the server to the file with suffix. */
            // File docfilewithext = new file (filepath + ". + ext.tolowercase()); / / file with suffix
            // docFile.renameTo(docFileWithExt);
            /* Converted filename */
            String filePath = sourceFile.getPath();
            File pdfFile;
            if (filePath.contains(".")) {
                pdfFile = new File(filePath.substring(0, filePath.lastIndexOf(".")) + ".pdf");
            } else {
                pdfFile = new File(filePath + ".pdf");
            }

            /* Determine whether the file to be converted actually exists */
            if (sourceFile.exists()) {
                /* Determine whether the file has been converted. If it has been converted, preview it directly. */
                if (!pdfFile.exists()) {
                    OpenOfficeConnection connection;
                    /* Open OpenOffice connection */
                    try {
                        connection = new SocketOpenOfficeConnection(openofficeHost, openofficePort);
                        connection.connect();
                    } catch (java.net.ConnectException e) {
                        log.warn("openOffice Not connected, reconnecting...");

                        // Start services for OpenOffice
                        String command = openofficeInstallPath + "program/soffice -headless -accept=\"socket,host=127.0.0.1,port=8100;urp;\" -nofirststartwizard";
                        Runtime.getRuntime().exec(command);

                        Thread.sleep(1000);

                        connection = new SocketOpenOfficeConnection(8100);
                        connection.connect();

                        log.warn("openOffice Reconnect successful!!!");
                    }

                    try {
                        // DocumentConverter converter = new OpenOfficeDocumentConverter(connection);
                        DocumentConverter converter = new StreamOpenOfficeDocumentConverter(connection);
                        converter.convert(sourceFile, pdfFile);
                        connection.disconnect();

//                            Filepath = pdnfile. Getpath(); / / path after file conversion
                        sourceFile = pdfFile;
                        response.setContentType("application/pdf");
                    } catch (OpenOfficeException e) {
                        e.printStackTrace(); // Failed to read conversion file
                        log.info("Failed to read conversion file!!!");
                        return;
                    } finally { // When exception occurs, the connection will not be automatically cut off, and the program will be hung all the time.
                        try {
                            if (connection != null) {
                                connection.disconnect();
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                } else {
//                        filePath = pdfFile.getPath(); / / the file has been converted
                    sourceFile = pdfFile;
                    response.setContentType("application/pdf");
                }
            } else {
                log.info("The document to be previewed does not exist on the server!!!");
                // File does not exist, return directly
                return;
            }
        }

        /**
          * Write the file to the output stream and display it on the interface to achieve preview effect
          */
        ios = new FileInputStream(sourceFile);
        os = response.getOutputStream();
        int read = 0;
        byte[] buffer = new byte[1024 * 1024];
        while ((read = ios.read(buffer)) != -1) {
            os.write(buffer, 0, read);
        }
        os.flush();
    } catch (Exception e) {
        e.printStackTrace();
        try {
            if (null != ios) {
                ios.close();
            }
            if (null != os) {
                os.close();
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}



< center > sponsored by < / center >
<center><img src="https://user-gold-cdn.xitu.io...;h=1080&f=png&s=342366" width="240" align=center /><center>

<center><img src="https://user-gold-cdn.xitu.io...;h=299&f=gif&s=20783" width="240" align=center /><center>

Please indicate: Online preview solution for uni app files

Posted by ShawnK on Thu, 24 Oct 2019 19:17:06 -0700