在React Native中查看PDF

Axe*_*eva 16 pdf webview react-native

任何人都可以提供在React Native中显示PDF的示例代码吗?iOS和Android.

这就是我尝试过的:

  render: function() {
    return <WebView
      source={require('./my.pdf')}
      />
  }
Run Code Online (Sandbox Code Playgroud)

^这导致死亡的红色屏幕与"无法解决模块"错误.

  render: function() {
    return <WebView
      source={{uri: 'my.pdf'}}
      />
  }
Run Code Online (Sandbox Code Playgroud)

^这会在WebView中显示"Error Loading Page"消息."在此服务器上找不到请求的URL"

我知道iOS能够在UIWebView中显示PDF.我认为Android可以做同样的事情.必须存在如何指定我缺少的源.

Axe*_*eva 24

好的,对于后代,这是我如何解决这个问题:

2017年9月13日更新:

有一个新的NPM模块,使整个过程更容易.我建议使用它,而不是我原来的答案:

反应天然-PDF

安装后,渲染PDF就像这样简单:

export default class YourClass extends Component {
  constructor(props) {
    super(props);
    this.pdf = null;
  }

  render() {
    let yourPDFURI = {uri:'bundle-assets://pdf/YourPDF.pdf', cache: true};

    return <View style={{flex: 1}}>
      <Pdf ref={(pdf)=>{this.pdf = pdf;}}
        source={yourPDFURI}
        style={{flex: 1}}
        onError={(error)=>{console.log(error);}} />
    </View>
  }
}
Run Code Online (Sandbox Code Playgroud)

只需将您的实际pdf放在android/app/src/main/assets/pdf项目的文件夹中即可.

原答案:

iOS版

render: function() {
  return <WebView source={{uri: 'My.pdf'}}/>
}
Run Code Online (Sandbox Code Playgroud)

诀窍是你需要My.pdf在Xcode中包含你的项目,并确保它已添加到你的构建目标中.

只是将它复制到你的React Native项目文件夹是不够的.它必须是Xcode项目本身的一部分.

Android的

似乎Android直到5.0(Lollipop)才提供原生PDF查看器.为了解决这个问题,我必须使用三种关键技术:

  1. 从我的APK包中提取PDF并将其存储在files我的应用程序的文件夹中.这个答案非常有助于实现这一点:

Android:如何将文件从'assets'文件夹复制到SD卡?

我调整了一些代码,以便文件不会发送sdcard到我的应用程序的files文件夹.这是我添加到我的内容MainActivity.java

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);

  AssetManager assetManager = getAssets();
  String[] files = null;

  try {
      files = assetManager.list("pdf");
  } catch (IOException e) {
      Log.e("tag", "Failed to get asset file list.", e);
  }

  if (files != null) for (String filename : files) {
      InputStream in = null;
      OutputStream out = null;

      try {
        in = assetManager.open("pdf/" + filename);

        File outFile = new File(getFilesDir(), filename);
        out = new FileOutputStream(outFile);
        copyFile(in, out);
        Log.e("tag", "Copy was a success: " + outFile.getPath());
      } catch(IOException e) {
        Log.e("tag", "Failed to copy asset file: " + "pdf/" + filename, e);
      }
      finally {
          if (in != null) {
              try {
                  in.close();
              } catch (IOException e) {
                  // NOOP
              }
          }
          if (out != null) {
              try {
                  out.close();
              } catch (IOException e) {
                  // NOOP
              }
          }
      }
  }
}

private void copyFile(InputStream in, OutputStream out) throws IOException {
    byte[] buffer = new byte[1024];
    int read;
    while((read = in.read(buffer)) != -1){
      out.write(buffer, 0, read);
    }
}
Run Code Online (Sandbox Code Playgroud)

我还确保我的PDF assets/pdf文件夹在下面的文件夹中android/app/src/main

  1. 然后,我使用react-native-fs包获取我的PDF的绝对URL,该URL现在位于以下files文件夹中:

    var RNFS = require('react-native-fs');
    var absolutePath = RNFS.DocumentDirectoryPath + '/My.pdf';
    
    Run Code Online (Sandbox Code Playgroud)
  2. 完成所有这些后,我使用react-native-pdf-view实际加载和显示PDF:

    import PDFView from 'react-native-pdf-view';
    
    render: function() {
      var absolutePath = RNFS.DocumentDirectoryPath + '/My.pdf';
    
      return <PDFView
        ref={(pdf)=>{this.pdfView = pdf;}}
        src={absolutePath}
        style={ActharStyles.fullCover} />
    }
    
    Run Code Online (Sandbox Code Playgroud)

祝好运!


Mic*_*ård 8

为此问题的一个简单解决方案是将其设置<WebView> source/uri为:

https://drive.google.com/viewerng/viewer?embedded=true&url={your pdf url}’
Run Code Online (Sandbox Code Playgroud)

  • 实际上更好的解决方案是使用这个:https://github.com/mozilla/PDF.js/wiki/Viewer-options 因为它支持跳转到页码。据我所知,谷歌驱动器查看器对使用/天有限制 (4认同)