【问题标题】:Android download PDF from URL then open it with a PDF readerAndroid 从 URL 下载 PDF,然后使用 PDF 阅读器打开它
【发布时间】:2014-09-04 14:06:11
【问题描述】:

我正在尝试编写一个应用程序来从 URL 下载 PDF,将它们存储在 SD 上,然后由 Adob​​e PDF 阅读器或其他应用程序(能够打开 PDF)打开。

到目前为止,我已经“成功下载并存储在 SD 卡上”(但每次我尝试使用 PDF 阅读器打开 PDF 时,阅读器都会崩溃并说出现意外错误),例如,@987654321 @

这是我的下载器的代码:

//........code set ui stuff
//........code set ui stuff
     new DownloadFile().execute(fileUrl, fileName); 


private class DownloadFile extends AsyncTask<String, Void, Void>{

        @Override
        protected Void doInBackground(String... strings) {
            String fileUrl = strings[0];   // -> http://maven.apache.org/maven-1.x/maven.pdf
            String fileName = strings[1];  // -> maven.pdf
            String extStorageDirectory = Environment.getExternalStorageDirectory().toString();
            File folder = new File(extStorageDirectory, "testthreepdf");
            folder.mkdir();

            File pdfFile = new File(folder, fileName);

            try{
                pdfFile.createNewFile();
            }catch (IOException e){
                e.printStackTrace();
            }
            FileDownloader.downloadFile(fileUrl, pdfFile);
            return null;
        }
    }



public class FileDownloader {
    private static final int  MEGABYTE = 1024 * 1024;

    public static void downloadFile(String fileUrl, File directory){
        try {

            URL url = new URL(fileUrl);
            HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
            urlConnection.setRequestMethod("GET");
            urlConnection.setDoOutput(true);
            urlConnection.connect();

            InputStream inputStream = urlConnection.getInputStream();
            FileOutputStream fileOutputStream = new FileOutputStream(directory);
            int totalSize = urlConnection.getContentLength();

            byte[] buffer = new byte[MEGABYTE];
            int bufferLength = 0;
            while((bufferLength = inputStream.read(buffer))>0 ){
                fileOutputStream.write(buffer, 0, bufferLength);
            }
            fileOutputStream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在调试模式下,我可以看到应用下载它并将此 PDF 存储在 /storage/sdcard/testpdf/maven.pdf 上。但是,我猜该文件可能在下载过程中以某种方式损坏,因此无法正常打开...

这是我打算如何用另一个阅读器应用程序打开它的代码:

File pdfFile = new File(Environment.getExternalStorageDirectory() + "/testthreepdf/" + fileName);  // -> filename = maven.pdf
                    Uri path = Uri.fromFile(pdfFile);
                    Intent pdfIntent = new Intent(Intent.ACTION_VIEW);
                    pdfIntent.setDataAndType(path, "application/pdf");
                    pdfIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

                    try{
                        startActivity(pdfIntent);
                    }catch(ActivityNotFoundException e){
                        Toast.makeText(documentActivity, "No Application available to view PDF", Toast.LENGTH_SHORT).show();
                    }

【问题讨论】:

  • byte[] buffer = new byte[MEGABYTE]; 这条线是什么意思?它是否为缓冲区分配了 1 GB 的空间?

标签: android pdf download httpurlconnection fileinputstream


【解决方案1】:
String imageurl = response.optString("PdfUrl");
                            DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
                            DownloadManager.Request request = new DownloadManager.Request(Uri.parse(imageurl));

                            request.allowScanningByMediaScanner();
                            request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); //Notify client once download is completed!


                            dm.enqueue(request);

【讨论】:

    【解决方案2】:

    您好,问题出在 FileDownloader 类中

     urlConnection.setRequestMethod("GET");
        urlConnection.setDoOutput(true);
    

    您需要删除以上两行,一切都会正常工作。如果问题按预期工作,请将问题标记为已回答。

    同一问题的最新解决方案更新Android PDF Write / Read using Android 9 (API level 28)

    用屏幕截图附加工作代码。

    MainActivity.java

    package com.example.downloadread;
    
    import java.io.File;
    import java.io.IOException;
    
    import android.app.Activity;
    import android.content.ActivityNotFoundException;
    import android.content.Intent;
    import android.net.Uri;
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.os.Environment;
    import android.view.Menu;
    import android.view.View;
    import android.widget.Toast;
    
    public class MainActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }
    
        public void download(View v)
        {
            new DownloadFile().execute("http://maven.apache.org/maven-1.x/maven.pdf", "maven.pdf"); 
        }
    
        public void view(View v)
        {
            File pdfFile = new File(Environment.getExternalStorageDirectory() + "/testthreepdf/" + "maven.pdf");  // -> filename = maven.pdf
            Uri path = Uri.fromFile(pdfFile);
            Intent pdfIntent = new Intent(Intent.ACTION_VIEW);
            pdfIntent.setDataAndType(path, "application/pdf");
            pdfIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    
            try{
                startActivity(pdfIntent);
            }catch(ActivityNotFoundException e){
                Toast.makeText(MainActivity.this, "No Application available to view PDF", Toast.LENGTH_SHORT).show();
            }
        }
    
        private class DownloadFile extends AsyncTask<String, Void, Void>{
    
            @Override
            protected Void doInBackground(String... strings) {
                String fileUrl = strings[0];   // -> http://maven.apache.org/maven-1.x/maven.pdf
                String fileName = strings[1];  // -> maven.pdf
                String extStorageDirectory = Environment.getExternalStorageDirectory().toString();
                File folder = new File(extStorageDirectory, "testthreepdf");
                folder.mkdir();
    
                File pdfFile = new File(folder, fileName);
    
                try{
                    pdfFile.createNewFile();
                }catch (IOException e){
                    e.printStackTrace();
                }
                FileDownloader.downloadFile(fileUrl, pdfFile);
                return null;
            }
        }
    
    
    }
    

    FileDownloader.java

    package com.example.downloadread;
    
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.MalformedURLException;
    import java.net.URL;
    
    public class FileDownloader {
        private static final int  MEGABYTE = 1024 * 1024;
    
        public static void downloadFile(String fileUrl, File directory){
            try {
    
                URL url = new URL(fileUrl);
                HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
                //urlConnection.setRequestMethod("GET");
                //urlConnection.setDoOutput(true);
                urlConnection.connect();
    
                InputStream inputStream = urlConnection.getInputStream();
                FileOutputStream fileOutputStream = new FileOutputStream(directory);
                int totalSize = urlConnection.getContentLength();
    
                byte[] buffer = new byte[MEGABYTE];
                int bufferLength = 0;
                while((bufferLength = inputStream.read(buffer))>0 ){
                    fileOutputStream.write(buffer, 0, bufferLength);
                }
                fileOutputStream.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

    AndroidManifest.xml

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.downloadread"
        android:versionCode="1"
        android:versionName="1.0" >
    
        <uses-sdk
            android:minSdkVersion="14"
            android:targetSdkVersion="18" />
        <uses-permission android:name="android.permission.INTERNET"></uses-permission>
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
        <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
        <application
            android:allowBackup="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:theme="@style/AppTheme" >
            <activity
                android:name="com.example.downloadread.MainActivity"
                android:label="@string/app_name" >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    
    </manifest>
    

    activity_main.xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context=".MainActivity" >
    
        <Button
            android:id="@+id/button1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true"
            android:layout_marginTop="15dp"
            android:text="download"
            android:onClick="download" />
    
        <Button
            android:id="@+id/button2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentRight="true"
            android:layout_below="@+id/button1"
            android:layout_marginTop="38dp"
            android:text="view"
            android:onClick="view" />
    
    </RelativeLayout>
    

    【讨论】:

    • 嗨,扎克,通过删除这两行,它可以工作,我可以在我的移动设备上下载和阅读。但不知何故,每次我尝试在模拟器上阅读 DLed pdf 时,它都会崩溃,知道为什么吗?我使用这个 adobe reader apk -> appsapk.com/adobe-reader 你是在模拟器还是你的设备上阅读的?谢谢
    • 另外,我想知道为什么通过删除这两行,应用程序可以工作?幕后故事是什么?谢谢
    • 我的理解是从桌面应用程序下载 PDF 时需要指定 GET / POST,但是在 Android 中根据响应代码决定如何下载。因此,不需要该行。另外 doOutput 不是必需的,因为我们正在流式传输和写入 pdf 文件。如果您需要更多详细信息,请告诉我。感谢您将其标记为已回答。祝你有美好的一天。
    • @MohammedZackria-Zack 你的例子很好,但是当我打开另一个 Pdf 以前的文件自动删除时出现问题。请告诉我如何防止文件删除请帮助我
    • @Spritzig 我已经更新了你的问题的解决方案stackoverflow.com/questions/55816746/…
    【解决方案3】:

    从这里下载源代码 (Open Pdf from url in Android Programmatically)

    MainActivity.java

    package com.deepshikha.openpdf;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.webkit.WebView;
    import android.webkit.WebViewClient;
    import android.widget.ProgressBar;
    
    public class MainActivity extends AppCompatActivity {
        WebView webview;
        ProgressBar progressbar;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            webview = (WebView)findViewById(R.id.webview);
            progressbar = (ProgressBar) findViewById(R.id.progressbar);
            webview.getSettings().setJavaScriptEnabled(true);
            String filename ="http://www3.nd.edu/~cpoellab/teaching/cse40816/android_tutorial.pdf";
            webview.loadUrl("http://docs.google.com/gview?embedded=true&url=" + filename);
    
            webview.setWebViewClient(new WebViewClient() {
    
                public void onPageFinished(WebView view, String url) {
                    // do your stuff here
                    progressbar.setVisibility(View.GONE);
                }
            });
    
        }
    }
    

    谢谢!

    【讨论】:

      【解决方案4】:

      这是下载和查看 PDF 文件的最佳方法。您可以从任何地方调用它

      PDFTools.showPDFUrl(context, url);

      下面放代码。它会正常工作

      public class PDFTools {
      private static final String TAG = "PDFTools";
      private static final String GOOGLE_DRIVE_PDF_READER_PREFIX = "http://drive.google.com/viewer?url=";
      private static final String PDF_MIME_TYPE = "application/pdf";
      private static final String HTML_MIME_TYPE = "text/html";
      
      
      public static void showPDFUrl(final Context context, final String pdfUrl ) {
          if ( isPDFSupported( context ) ) {
              downloadAndOpenPDF(context, pdfUrl);
          } else {
              askToOpenPDFThroughGoogleDrive( context, pdfUrl );
          }
      }
      
      
      @TargetApi(Build.VERSION_CODES.GINGERBREAD)
      public static void downloadAndOpenPDF(final Context context, final String pdfUrl) {
          // Get filename
          //final String filename = pdfUrl.substring( pdfUrl.lastIndexOf( "/" ) + 1 );
          String filename = "";
          try {
              filename = new GetFileInfo().execute(pdfUrl).get();
          } catch (InterruptedException e) {
              e.printStackTrace();
          } catch (ExecutionException e) {
              e.printStackTrace();
          }
          // The place where the downloaded PDF file will be put
          final File tempFile = new File( context.getExternalFilesDir( Environment.DIRECTORY_DOWNLOADS ), filename );
          Log.e(TAG,"File Path:"+tempFile);
          if ( tempFile.exists() ) {
              // If we have downloaded the file before, just go ahead and show it.
              openPDF( context, Uri.fromFile( tempFile ) );
              return;
          }
      
          // Show progress dialog while downloading
          final ProgressDialog progress = ProgressDialog.show( context, context.getString( R.string.pdf_show_local_progress_title ), context.getString( R.string.pdf_show_local_progress_content ), true );
      
          // Create the download request
          DownloadManager.Request r = new DownloadManager.Request( Uri.parse( pdfUrl ) );
          r.setDestinationInExternalFilesDir( context, Environment.DIRECTORY_DOWNLOADS, filename );
          final DownloadManager dm = (DownloadManager) context.getSystemService( Context.DOWNLOAD_SERVICE );
          BroadcastReceiver onComplete = new BroadcastReceiver() {
              @Override
              public void onReceive(Context context, Intent intent) {
                  if ( !progress.isShowing() ) {
                      return;
                  }
                  context.unregisterReceiver( this );
      
                  progress.dismiss();
                  long downloadId = intent.getLongExtra( DownloadManager.EXTRA_DOWNLOAD_ID, -1 );
                  Cursor c = dm.query( new DownloadManager.Query().setFilterById( downloadId ) );
      
                  if ( c.moveToFirst() ) {
                      int status = c.getInt( c.getColumnIndex( DownloadManager.COLUMN_STATUS ) );
                      if ( status == DownloadManager.STATUS_SUCCESSFUL ) {
                          openPDF( context, Uri.fromFile( tempFile ) );
                      }
                  }
                  c.close();
              }
          };
          context.registerReceiver( onComplete, new IntentFilter( DownloadManager.ACTION_DOWNLOAD_COMPLETE ) );
      
          // Enqueue the request
          dm.enqueue( r );
      }
      
      
      public static void askToOpenPDFThroughGoogleDrive( final Context context, final String pdfUrl ) {
          new AlertDialog.Builder( context )
                  .setTitle( R.string.pdf_show_online_dialog_title )
                  .setMessage( R.string.pdf_show_online_dialog_question )
                  .setNegativeButton( R.string.pdf_show_online_dialog_button_no, null )
                  .setPositiveButton( R.string.pdf_show_online_dialog_button_yes, new DialogInterface.OnClickListener() {
                      @Override
                      public void onClick(DialogInterface dialog, int which) {
                          openPDFThroughGoogleDrive(context, pdfUrl);
                      }
                  })
                  .show();
      }
      
      public static void openPDFThroughGoogleDrive(final Context context, final String pdfUrl) {
          Intent i = new Intent( Intent.ACTION_VIEW );
          i.setDataAndType(Uri.parse(GOOGLE_DRIVE_PDF_READER_PREFIX + pdfUrl ), HTML_MIME_TYPE );
          context.startActivity( i );
      }
      
      public static final void openPDF(Context context, Uri localUri ) {
          Intent i = new Intent( Intent.ACTION_VIEW );
          i.setDataAndType( localUri, PDF_MIME_TYPE );
          context.startActivity( i );
      }
      
      public static boolean isPDFSupported( Context context ) {
          Intent i = new Intent( Intent.ACTION_VIEW );
          final File tempFile = new File( context.getExternalFilesDir( Environment.DIRECTORY_DOWNLOADS ), "test.pdf" );
          i.setDataAndType( Uri.fromFile( tempFile ), PDF_MIME_TYPE );
          return context.getPackageManager().queryIntentActivities( i, PackageManager.MATCH_DEFAULT_ONLY ).size() > 0;
      }
      
      // get File name from url
      static class GetFileInfo extends AsyncTask<String, Integer, String>
      {
          protected String doInBackground(String... urls)
          {
              URL url;
              String filename = null;
              try {
                  url = new URL(urls[0]);
                  HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                  conn.connect();
                  conn.setInstanceFollowRedirects(false);
                  if(conn.getHeaderField("Content-Disposition")!=null){
                      String depo = conn.getHeaderField("Content-Disposition");
      
                      String depoSplit[] = depo.split("filename=");
                      filename = depoSplit[1].replace("filename=", "").replace("\"", "").trim();
                  }else{
                      filename = "download.pdf";
                  }
              } catch (MalformedURLException e1) {
                  e1.printStackTrace();
              } catch (IOException e) {
              }
              return filename;
          }
      
          @Override
          protected void onPreExecute() {
              super.onPreExecute();
          }
          @Override
          protected void onPostExecute(String result) {
              super.onPostExecute(result);
              // use result as file name
          }
      }
      

      }

      试试看。它会起作用的,享受吧

      【讨论】:

      • 这个过程有点长
      • 在替换 openPDF(context, FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".my.package.name.provider", tempFile) 等 openPDF 方法后,这对我有用);它在这里描述:stackoverflow.com/a/38858040/1492681
      • 请注意,尽管 Google 网络服务 http://drive.google.com/viewer 并未作为 API 正式推出供公众使用,而且他们可以随时将其撤下,而无需任何公开通知。
      猜你喜欢
      • 1970-01-01
      • 2011-02-26
      • 1970-01-01
      • 2012-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多