uni-app在线预览PDF

需求

文件不可以通过文件地址直接访问,要通过文件流的形式在线预览

工具

基于pdfjs封装的组件(别人封装的),用webview访问本地网页

遇到的问题

  • 开始的时候以为他可以自己获取文件流并处理,所以直接将请求地址传进去了
  • 意识到他不能处理blob,手动处理,将blob转为url
  • 正常处理了blob,处理后的url传进去,页数显示正常,但内容为空

踩坑的过程

先看一下文件路径,资源会在文末分享

image-20201129115456698

1 创建webview访问这个viewer.html

<template>
    <view style="width: 100%;" >
        <web-view :src="allUrl"></web-view>
    </view>
</template>

<script>
  export default {
    data() {
      return {
        allUrl:'',
                viewerUrl: '/hybrid/html/web/viewer.html', // 格式化文件流的一个js 文件 文末会分享出来
      }
    },
    onLoad(options) {
            let {url, title} = options
            uni.setNavigationBarTitle({
                title: title
            })
      this.allUrl = this.viewerUrl + url
    }
</script>

传进来的url是/read/tryread?bookId=${this.bookId},但是pdfjs默认是不能处理这种形式的url的

2 先获取二进制流,转url

在这个页面请求数据,然后转url传到pdfjs中,然后改进代码

<template>
    <view style="width: 100%;" >
        <web-view :src="allUrl"></web-view>
    </view>
</template>

<script>
    export default {
        data() {
            return {
                allUrl:'',
                viewerUrl: '/hybrid/html/web/viewer.html', // 格式化文件流的一个js 文件 文末会分享出来
            }
        },
        methods: {
            getFile(url) {
                uni.request({
                    url: this.$photoHeader + 'api' + url,
                    header: {
                        'Content-Type': 'application/pdf',
                        'authorization': this.$store.getters.getToken
                    },
                    success: (res) => {
                        // ↓↓↓↓注意下面这里
                        const fileUrl = this.transBlobToUrl(res.data)
                        this.allUrl = this.viewerUrl + '?file=' + fileUrl
                        console.log(this.allUrl);
                    },
                });
            },
            transBlobToUrl(file) {
              // 将获取的blob转化为url
              // console.log(file);
              let url = null;
                if (window.createObjectURL != undefined) { // basic
                  url = window.createObjectURL(file);
                } else if (window.webkitURL != undefined) { // webkit or chrome
                  try {
                    url = window.webkitURL.createObjectURL(file);
                  } catch (error) {
                    console.log(error)
                  }
                } else if (window.URL != undefined) { // mozilla(firefox)
                  try {
                    url = window.URL.createObjectURL(file);
                  } catch (error) {
                      console.log(1);
                    console.log(error)
                  }
                }
                return url;
            },
        },
        onLoad(options) {
            let {url, title} = options
            uni.setNavigationBarTitle({
                title: title
            })
            this.getFile(decodeURIComponent(url))
            
          }
    }
</script>

这应该可以获取到url了,但是还是不行,看到getFile中标记的地方了吗,问题就在这,他这里拿到的数据成了string,需要将string转为blob格式

将获取url的语句改为 const fileUrl = this.transBlobToUrl(new Blob([res.data]))

最后一步,临门一脚

这时候数据拿到了,也转成url了,再回到页面中,!!!白屏,但是页数正常

image-20201129120746717

查了好久之后发现,需要将响应格式声明为arraybuffer,也就是这样

image-20201129120913665

然后再看页面,完美!

image-20201129120932353

插件地址:
链接: https://pan.baidu.com/s/1xTTQPVWfJEVnY0hWlj7gdg 提取码: t8mn


前端小白