web-dev-qa-db-fra.com

Afficher un PDF in React Native

Quelqu'un peut-il fournir un exemple de code pour afficher un PDF in React Native? IOS et Android.

Voici ce que j'ai essayé:

  render: function() {
    return <WebView
      source={require('./my.pdf')}
      />
  }

^ Il en résulte un écran rouge de la mort avec l'erreur "Impossible de résoudre le module".

  render: function() {
    return <WebView
      source={{uri: 'my.pdf'}}
      />
  }

^ Cela donne un message "Erreur de chargement de la page" dans WebView. "L'URL demandée est introuvable sur ce serveur"

Je sais que iOS est capable d'afficher un PDF dans une UIWebView. Je suppose que Android peut faire de même. Il doit y avoir quelque chose dans la façon dont la source est spécifiée qui Je manque.

14
Axeva

D'accord, pour les générations futures, voici comment j'ai résolu ce problème:

Mis à jour le 13 septembre 2017:

Il y a un nouveau module NPM qui rend tout ce processus beaucoup plus facile. Je suggère de l'utiliser à l'avenir au lieu de ma réponse d'origine ci-dessous:

react-native-pdf

Une fois installé, le rendu du PDF est aussi simple que cela:

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>
  }
}

Mettez simplement votre pdf dans le Android/app/src/main/assets/pdf dossier de votre projet.

Réponse originale:

iOS

render: function() {
  return <WebView source={{uri: 'My.pdf'}}/>
}

L'astuce est que vous devez inclure My.pdf dans votre projet dans Xcode et assurez-vous qu'il est ajouté à votre cible de génération.

Le copier simplement dans votre dossier React Native project n'était pas suffisant. Il devait faire partie du projet Xcode lui-même.

Android

Il semble que Android n'a pas fourni de visionneuse native PDF jusqu'à 5.0 (Lollipop). Pour contourner ce problème, j'ai dû utiliser trois clés techniques:

  1. Tirez le PDF hors de mon package APK et stockez-le dans le dossier files de mon application. Cette réponse SO a été très utile pour accomplir cette:

Android: Comment copier des fichiers du dossier 'assets' vers sdcard?

J'ai légèrement modifié le code pour que le fichier n'aille pas dans un dossier sdcard mais dans le dossier files de mon application. Voici ce que j'ai ajouté à mon 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);
    }
}

Je me suis également assuré que mon PDF est dans le assets/pdf dossier sous Android/app/src/main

  1. J'ai ensuite utilisé le package react-native-fs pour obtenir l'URL absolue de mon PDF, qui se trouve maintenant dans le dossier files:

    var RNFS = require('react-native-fs');
    var absolutePath = RNFS.DocumentDirectoryPath + '/My.pdf';
    
  2. Avec tout cela en place, j'ai utilisé react-native-pdf-view pour charger et afficher le 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} />
    }
    

Bonne chance!

23
Axeva

Une solution simple à ce problème consiste à définir <WebView>source/uri pour ça:

https://drive.google.com/viewerng/viewer?embedded=true&url={your pdf url}’
7

Ajoutez simplement style={{flex:1}} dans la balise de vue d'ouverture de votre retour et ça devrait aller.