【问题标题】:Open pdf file url which is stored in Firebase storage打开存储在 Firebase 存储中的 pdf 文件 url
【发布时间】:2017-04-06 10:47:24
【问题描述】:

我已将 Pdf 文件上传到 Firebase 存储,在将 pdf 文件上传到 Firebase 存储后,我得到了下载网址。现在我想在我的应用程序中从这个下载 url 打开 pdf 文件。

以下是我将 pdf 文件上传到 firebase 存储后得到的网址。

https://firebasestorage.googleapis.com/v0/b/realtime-chat-46f4c.appspot.com/o/documents%2Fbf307aa5-79ae-4532-8128-ee394537b357.pdf?alt=media&token=2d0c5329-4717-4adc-9418-6614913e5bfa

现在我想打开一个查看此 pdf 文件的意图,为此我使用了以下代码:

String url = "https://firebasestorage.googleapis.com/v0/b/realtime-chat-46f4c.appspot.com/o/documents%2Fbf307aa5-79ae-4532-8128-ee394537b357.pdf?alt=media&token=2d0c5329-4717-4adc-9418-6614913e5bfa";

Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(url), "application/pdf");
startActivity(Intent.createChooser(intent, "Choose an Application:"));

我的手机有可以打开这个pdf文件的应用程序,但它仍然说没有安装任何应用程序来查看这个文件。

如果我在 File 中转换这个 url 并使用下面的代码,那么应用程序的选择器会被打开,但它会给出文件无法打开的错误。

Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
File file = new File(name);
intent.setDataAndType(Uri.fromFile(file), "aplication/pdf");

我看到很多回答说先下载文件再打开,但我不想下载文件,我只想查看。

如果有人对此有任何想法,请帮助我。

非常感谢。

【问题讨论】:

  • 当你说“它给出了无法打开文件的错误”时,你能更具体一点吗?您是否在某些日志中看到了这一点?请准确展示您所看到的内容。

标签: android pdf firebase firebase-storage


【解决方案1】:

你应该使用意图选择器

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(url), "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
Intent newIntent = Intent.createChooser(intent, "Open File");
try {
    startActivity(newIntent);
} catch (ActivityNotFoundException e) {
    // Instruct the user to install a PDF reader here, or something
} 

【讨论】:

  • 我已经尝试过了,但是它没有打开 Intent 选择器并说没有安装应用程序来阅读这个,但我已经在我的设备中安装了 Pdf 阅读器。
【解决方案2】:

您的手机未检测到 PDF,因为您使用的 URL 是字符串对象而不是 PDF 对象。从技术上讲,除非您下载 PDF,否则它永远不应以 PDF 格式从手机打开。手机上的 PDF 查看器只有在 Android 操作系统告诉他们它有一个有效的 PDF 文件时才会被激活。请查看任何 PDF 库的源代码以更好地理解这一点 -> https://android-arsenal.com/tag/72?sort=created

但是,要回答您的问题,您应该尝试将您的 URL 作为 URL 打开。它将激活您手机上的浏览器,进而检测到它需要 PDF 阅读器并激活相应的阅读器。

类似

String url = "https://firebasestorage.googleapis.com/v0/b/realtime-chat-46f4c.appspot.com/o/documents%2Fbf307aa5-79ae-4532-8128-ee394537b357.pdf?alt=media&token=2d0c5329-4717-4adc-9418-6614913e5bfa";


public void openWebPage(String url) {
    Uri webpage = Uri.parse(url);
    Intent intent = new Intent(Intent.ACTION_VIEW, webpage);
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivity(intent);
    }
}

但是,我认为您只想验证文件是否已成功上传。如果手机上有本地副本,则只需打开本地副本,而不是下载另一个副本。如果是这种情况,那么我建议使用文件元数据来实现这一点。类似的东西:

 // Create file metadata including the content type
StorageMetadata metadata = new StorageMetadata.Builder()
        .setCustomMetadata("myPDFfile", "localPDFfileName")
        .build();

// Upload the file and metadata
uploadTask = storageRef.child("pdf/localPDFfileName.pdf").putFile(file, metadata);

然后在您的成功侦听器上检索文件元数据。如果已下载并且看起来完整,则从本地手机存储中打开 PDF。如果没有,请尝试从我在帖子开头提到的 downloadURL 下载。这应该涵盖您尝试进行的验证。

如果我没有正确理解您的问题,请详细说明。我会捡起来并相应地修改我的回复。

【讨论】:

  • "现在我想打开一个意图来查看这个 pdf 文件" 我们正在寻找预览 pdf 文件,而不是下载它。
  • @KarloA.López - 是的,我明白这一点。但是,如果不下载内容,则无法预览服务器上的 PDF。因此,我建议使用元数据。
  • 最后这就是我所做的,将 PDF 下载到临时文件并使用 PDF viewer 显示,我正在寻找一个更简单的解决方案,很遗憾 http://drive.google.com/viewerng/viewer?embedded=true&url= 不适用于 firebase pdf文件。
  • @KarloA.López - 就像我提到的,更简单的解决方案是匹配上传文件和本地文件之间的关键元数据。对于像 GoogleDrive 这样的嵌入式阅读器功能,您可以尝试在服务器端编写 Firebase 功能 - 代码。它可以为您上传的文件创建预览图像,您可以在应用程序中使用 webview 显示该图像。与谷歌驱动器相同的技术
【解决方案3】:

请将以下文件/方法添加到您的项目中

  1. PdfDownloader.java
  2. PDFDownloaderAsyncTask.java

然后使用以下方法handleViewPdf查看pdf:

private void handleViewPdf () {

    File folder = getAppDirectory(context);
    String fileName = "test.pdf";// getPdfFileName(pdfUrl);
    File pdfFile = new File(folder, fileName);

    if (pdfFile.exists () && pdfFile.length () > 0) {
        openPDFFile (context, Uri.fromFile(pdfFile));
    }
    else {
        if (pdfFile.length () == 0) {
            pdfFile.delete ();
        }
        try {
            pdfFile.createNewFile ();
        }
        catch (IOException e) {
            e.printStackTrace ();
        }
        ArrayList<String> fileNameAndURL = new ArrayList<> ();
        fileNameAndURL.add (pdfFile.toString ());
        fileNameAndURL.add (pdfUrl);
        fileNameAndURL.add (fileName);
        if (pdfDownloaderAsyncTask == null) {
            pdfDownloaderAsyncTask = new PDFDownloaderAsyncTask (context, pdfFile);
        }
        if (hasInternetConnection (context)) {
            if (!pdfDownloaderAsyncTask.isDownloadingPdf ()) {
                pdfDownloaderAsyncTask = new PDFDownloaderAsyncTask (context, pdfFile);
                pdfDownloaderAsyncTask.execute (fileNameAndURL);
            }
        }
        else {
            //show error
        }
    }
}

PDFDownloaderAsyncTask.java

    import java.io.File;
    import java.util.ArrayList;

    import android.content.Context;
    import android.net.Uri;
    import android.os.AsyncTask;
    import android.os.Handler;
    import android.text.TextUtils;
    import android.widget.Toast;


    public class PDFDownloaderAsyncTask extends AsyncTask<ArrayList<String>, Void, String> {

        private boolean isDownloadingPdf = false;

        private File    file;
        private Context context;

        public PDFDownloaderAsyncTask (Context context, File file) {

            this.file = file;
            this.context = context;
            this.isDownloadingPdf = false;
        }

        public boolean isDownloadingPdf () {

            return this.isDownloadingPdf;
        }

        @Override
        protected void onPreExecute () {

            super.onPreExecute ();
            //show loader etc
        }

        @Override
        protected String doInBackground (ArrayList<String>... params) {

            isDownloadingPdf = true;
            File file = new File (params[0].get (0));
            String fileStatus = PdfDownloader.downloadFile (params[0].get (1), file);
            return fileStatus;
        }

        @Override
        protected void onPostExecute (String result) {

            super.onPostExecute (result);
            Loader.hideLoader ();
            if (!TextUtils.isEmpty (result) && result.equalsIgnoreCase (context.getString (R.string.txt_success))) {
                showPdf ();
            }
            else {
                isDownloadingPdf = false;
                Toast.makeText (context, context.getString (R.string.error_could_not_download_pdf), Toast.LENGTH_LONG).show ();
                file.delete ();
            }
        }

        @Override
        protected void onCancelled () {

            isDownloadingPdf = false;
            super.onCancelled ();
            //Loader.hideLoader ();
        }

        @Override
        protected void onCancelled (String s) {

            isDownloadingPdf = false;
            super.onCancelled (s);
            //Loader.hideLoader ();
        }

        private void showPdf () {

            new Handler ().postDelayed (new Runnable () {
                @Override
                public void run () {

                    isDownloadingPdf = false;
                    openPDFFile (context, Uri.fromFile (file));
                }
            }, 1000);
        }
    }

PdfDownloader.java

package com.pdf;

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 PdfDownloader {
    private static final int MEGABYTE = 1024 * 1024;

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

        String downloadStatus;
        try {

            URL url = new URL (fileUrl);
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection ();
            urlConnection.connect ();

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

            Log.d ("PDF", "Total size: " + totalSize);
            byte[] buffer = new byte[MEGABYTE];
            int bufferLength = 0;
            while ((bufferLength = inputStream.read (buffer)) > 0) {
                fileOutputStream.write (buffer, 0, bufferLength);
            }
            downloadStatus = "success";
            fileOutputStream.close ();
        }
        catch (FileNotFoundException e) {
            downloadStatus = "FileNotFoundException";
            e.printStackTrace ();
        }
        catch (MalformedURLException e) {
            downloadStatus = "MalformedURLException";
            e.printStackTrace ();
        }
        catch (IOException e) {
            downloadStatus = "IOException";
            e.printStackTrace ();
        }
        Log.d ("PDF", "Download Status: " + downloadStatus);
        return downloadStatus;
    }


    public static void openPDFFile (Context context, Uri path) {

        Intent intent = new Intent (Intent.ACTION_VIEW);
        intent.setDataAndType (path, "application/pdf");
        intent.setFlags (Intent.FLAG_ACTIVITY_CLEAR_TOP);
        try {
            context.startActivity (intent);
        }
        catch (ActivityNotFoundException e) {
            Toast.makeText (context, context.getString (R.string.txt_no_pdf_available), Toast.LENGTH_SHORT).show ();
        }
        Loader.hideLoader ();
    }

    public static File getAppDirectory (Context context) {

        String extStorageDirectory = Environment.getExternalStorageDirectory ().toString ();
        File folder = new File (extStorageDirectory, context.getString (R.string.app_folder_name).trim ());
        if (!folder.exists ()) {
            boolean success = folder.mkdirs();
            Log.d ("Directory", "mkdirs():" + success);
        }
        return folder;
    }

}

【讨论】:

  • 感谢您的努力,但我不想下载该文件,因为我是从我的设备上传它并且它已经存在于我的设备存储中,但在上传到 Firebase 存储之后,我想要使用存储 url 打开它。
  • 成功
  • PdfDownloader .downloadFile 返回“成功”
  • 这只是检查pdf是否下载成功。
  • 我收到 MalformedURLException。我传递的网址格式为 gs://// from firebase storage
【解决方案4】:

如果您想在您的应用程序中打开保存的 pdf 文件,而不是创建在其他应用程序中打开的意图,您可以使用以下库在 Xml 文件中创建 PdfView。 AndroidPdfViewer(这个库还提供了放大功能)

之后,如 Firebase Document 中所述,使用 firebase 存储中文件位置的保存路径引用以字节为单位获取文件并将其添加到您的 PdfView 中

例如,您的文件路径将类似于:“/folder1/yourfile.pdf”

pdfView = (PDFView) findViewById(R.id.pdfView);
mFirebaseStorage=FirebaseStorage.getInstance().getReference();

final long ONE_MEGABYTE = 1024 * 1024;

mFirebaseStorage.child("YourSavedFilePathRef").getBytes(ONE_MEGABYTE).addOnSuccessListener(new OnSuccessListener<byte[]>() {
    @Override
    public void onSuccess(byte[] bytes) {
 pdfView.fromBytes(bytes).load();
    }
}).addOnFailureListener(new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception e) {
        Toast.makeText(MainActivity.this,"download unsuccessful",Toast.LENGTH_LONG).show();
    }
});

【讨论】:

    【解决方案5】:

    简单的代码:)

    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        
    Uri fileuri =  Uri.parse("URL of file on storage") ;
    intent.setDataAndType(fileuri,"application/pdf");
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    Intent in = Intent.createChooser(intent,"open file");
    in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    context.startActivity(in);
    

    希望这可行:)

    【讨论】:

      【解决方案6】:

      尝试对您的 firebase 数据库文件 url 进行编码。它和我一起工作

      【讨论】:

        【解决方案7】:

        使用 Webview 查看 pdf 文件-

         WebView webview = (WebView) findViewById(R.id.webview);
            webview.getSettings().setJavaScriptEnabled(true);
            String pdf = "https://firebasestorage.googleapis.com/v0/b/realtime-chat-46f4c.appspot.com/o/documents%2Fbf307aa5-79ae-4532-8128-ee394537b357.pdf?alt=media&token=2d0c5329-4717-4adc-9418-6614913e5bfa";
            webview.loadUrl("http://drive.google.com/viewerng/viewer?embedded=true&url=" + pdf);
        

        【讨论】:

        • 这是一个选项,但我不想在 Webview 中查看 pdf 文件。我的要求是在已安装的 pdf 查看器中使用意图打开 pdf 文件。请帮助我如何实现这一目标。谢谢
        • 你试过这个吗?这种使用 google pdf 查看器加载远程 PDF 的方式甚至不起作用,它显示“没有可用的预览”。
        猜你喜欢
        • 2018-05-28
        • 1970-01-01
        • 2019-04-04
        • 2020-08-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-25
        • 1970-01-01
        相关资源
        最近更新 更多