You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

React Native Web跨端(iOS/Android/Web)PDF下载后打开方案求助

Downloading & Opening PDFs in React Native Web (Android + Windows Web)

Hey there! Let's work through how to handle downloading and opening PDFs in your cross-platform React Native Web app. I'll break this down by platform, starting with fixing your existing web code, then moving to Android-specific implementation.

1. Fixing Windows Browser (Web) Download & Opening

First, let's adjust your existing web download code—there are a couple of issues that might be causing problems:

  • Using mode: 'no-cors' creates an opaque response, which you can't convert to a blob properly. Unless your server explicitly blocks CORS, remove this line.
  • You're trying to access response.data, but fetch requires you to call response.blob() to get the binary data for the PDF.

Corrected Web Download Code

const downloadPDF = async () => {
  try {
    const response = await fetch('http://www.pdf995.com/samples/pdf.pdf', {
      method: 'GET',
      headers: {
        'Accept': 'application/pdf', // More appropriate header for PDF files
      },
    });

    if (!response.ok) throw new Error('Failed to download PDF');
    
    const blob = await response.blob();
    const pdfUrl = window.URL.createObjectURL(blob);
    
    // Trigger download
    const link = document.createElement('a');
    link.href = pdfUrl;
    link.setAttribute('download', 'sample.pdf'); // Replace with your dynamic filename
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link); // Clean up the DOM element
    
    // Store the URL for opening later
    setPdfUrl(pdfUrl);
  } catch (error) {
    console.error('PDF download error:', error);
    alert('Oops, something went wrong downloading the PDF!');
  }
};

Opening the PDF on Web

Once downloaded, you have a few options to open the PDF:

  • New Browser Tab: The simplest approach—use window.open() to launch the PDF in the browser's built-in viewer:
    const openPDFWeb = () => {
      if (pdfUrl) {
        window.open(pdfUrl, '_blank');
      } else {
        alert('Please download the PDF first!');
      }
    };
    
  • Embed in Your App: Use an iframe to display the PDF directly in your UI:
    {pdfUrl && (
      <iframe
        src={pdfUrl}
        width="100%"
        height="600px"
        title="PDF Viewer"
        style={{ border: '1px solid #ddd' }}
      />
    )}
    
  • Custom Viewer: For more control, use the react-pdf library to build a custom viewer. Install it first with npm install react-pdf, then use:
    import { Document, Page } from 'react-pdf';
    
    {pdfUrl && (
      <Document file={pdfUrl}>
        <Page pageNumber={1} style={{ width: '100%' }} />
        {/* Add pagination controls if needed */}
      </Document>
    )}
    

2. Android Implementation

For Android, you can't use web APIs directly—you'll need React Native libraries to handle file storage and opening. We'll use react-native-fs for downloading files to local storage, and either the system's default PDF viewer or react-native-pdf for in-app viewing.

Step 1: Install Dependencies

npm install react-native-fs react-native-pdf --save

(For React Native 0.60+, auto-linking will handle setup. For older versions, follow the libraries' manual linking guides.)

Step 2: Download PDF to Android Storage

import RNFS from 'react-native-fs';

const downloadPDFAndroid = async () => {
  try {
    const pdfRemoteUrl = 'http://www.pdf995.com/samples/pdf.pdf';
    // Save to external storage (user-accessible directory)
    const localFilePath = `${RNFS.ExternalDirectoryPath}/sample.pdf`;

    const downloadResult = await RNFS.downloadFile({
      fromUrl: pdfRemoteUrl,
      toFile: localFilePath,
    }).promise;

    if (downloadResult.statusCode === 200) {
      console.log('PDF saved to:', localFilePath);
      setPdfLocalPath(localFilePath);
    } else {
      throw new Error(`Download failed with status: ${downloadResult.statusCode}`);
    }
  } catch (error) {
    console.error('Android PDF download error:', error);
    alert('Failed to download PDF on Android!');
  }
};

Step 3: Open the PDF on Android

Option 1: Use System Default Viewer

First, add these permissions to your android/app/src/main/AndroidManifest.xml:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- For Android 13+, replace with: -->
<uses-permission android:name="android.permission.READ_MEDIA_DOCUMENTS" />

Then use React Native's Linking API to open the file:

import { Linking, Platform } from 'react-native';

const openPDFAndroid = async () => {
  if (!pdfLocalPath) {
    alert('Please download the PDF first!');
    return;
  }

  const fileUri = `file://${pdfLocalPath}`;
  const isViewerAvailable = await Linking.canOpenURL(fileUri);

  if (isViewerAvailable) {
    await Linking.openURL(fileUri);
  } else {
    alert('No PDF viewer app found on your device!');
  }
};

Option 2: In-App Viewing with react-native-pdf

If you want to display the PDF directly in your app instead of launching an external viewer:

import PDFView from 'react-native-pdf';

{Platform.OS === 'android' && pdfLocalPath && (
  <PDFView
    source={{ uri: `file://${pdfLocalPath}` }}
    style={{ flex: 1, width: '100%' }}
    onLoadComplete={(pageCount) => console.log(`PDF has ${pageCount} pages`)}
    onError={(error) => console.error('PDF view error:', error)}
  />
)}

3. Cross-Platform Button Handler

Wrap everything up into a single component that handles both platforms:

import { useState, Platform, View, Button } from 'react';
// Import your download/open functions here

const PDFComponent = () => {
  const [pdfUrl, setPdfUrl] = useState(null);
  const [pdfLocalPath, setPdfLocalPath] = useState(null);

  const handleDownload = async () => {
    if (Platform.OS === 'web') {
      await downloadPDF();
    } else if (Platform.OS === 'android') {
      await downloadPDFAndroid();
    }
  };

  const handleOpenPDF = () => {
    if (Platform.OS === 'web') {
      openPDFWeb();
    } else if (Platform.OS === 'android') {
      openPDFAndroid();
    }
  };

  return (
    <View style={{ padding: 20, gap: 10 }}>
      <Button title="Download PDF" onPress={handleDownload} />
      <Button title="显示PDF" onPress={handleOpenPDF} />
      {/* Add your PDF viewer component here */}
    </View>
  );
};

export default PDFComponent;

内容的提问来源于stack exchange,提问作者user

火山引擎 最新活动