如何使用 FPDF 和 Retrofit 库发送用于生成 PDF 的特定参数并将其下载到 Android

How to send a specific parameter for PDF generation using FPDF and Retrofit library and download it into Android

我想将 Android 中的可变参数键发送到 API 服务器中的 FPDF 变量,这将根据日期范围生成一组报告,但是 FPDF 中的变量 API 没有收到 Android 发送的变量。
这该怎么做?我应该使用哪个 Call<>

我已经尝试使用 Call<ResponseBody> 来发送参数。我还尝试测试它是否在 onResponse 以下成功连接到目标文件并且它响应为真。
但是,当需要将文件下载到设备中时,我尝试将下载 link 直接定位到服务器中的文件路径。
但是在打开下载的文件后,我得到的是空白数据 table,这说明 FPDF 中的变量没有收到发送的 Android 变量。

这是我的 downloadPDF() 方法,用于将参数发送到 FPDF API:

private void downloadPDF() {
        RestApi api = RetroFit.getInstanceRetrofit();
        Call<ResponseBody> printCall = api.getPrint(
                strDateFrom,
                strDateTo
        );
        printCall.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                downloadManager();
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                Toast.makeText(getContext(), "No data :(", Toast.LENGTH_SHORT).show();
            }
        });
    }

接口方法:

    @FormUrlEncoded
    @POST("somepath/get_print.php")
    Call<ResponseBody> getPrint(
            @Field("keyDateFrom") String from,
            @Field("keyDateTo") String to
    );

downloadManager()方法:

private void downloadManager() {
        DownloadManager downloadService = (DownloadManager) getActivity().getSystemService(Context.DOWNLOAD_SERVICE);
        Uri uri = Uri.parse("http://someweb.com/somefolder/get_print.php");
        DownloadManager.Request request = new DownloadManager.Request(uri);
        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
    }

还有我的get_print.php脚本:

<?php

include 'config.php';

$keyDateFrom = $_POST["keyDateFrom"];

$keyDateTo = $_POST["keyDateTo"];

require('fpdf.php');
$pdf = new FPDF('P','mm','A4');
$pdf->AddPage();

$pdf->Image('logo_hsp_transparan.png',10,10,30,15);

$pdf->SetLeftMargin(20);
$pdf->SetFont('Arial','B',16);
$pdf->Cell(190,7,'Daftar Peminjaman Kendaraan HSPnet',0,1,'C');
$pdf->SetFont('Arial','B',9);
$pdf->Cell(190,7,'Jl. Tanah Merdeka No.1, RT.10/RW.3, Rambutan, Ciracas, Kota Jakarta Timur',0,1,'C');
$pdf->Cell(10,7,'',0,1);

$pdf->SetFont('Arial','B',9);
$pdf->Cell(190,7, $keyDateFrom ,0,1,'C');
$pdf->SetFont('Arial','',9);
$pdf->Cell(190,7,'to',0,1,'C');
$pdf->SetFont('Arial','B',9);
$pdf->Cell(190,7, $keyDateTo ,0,1,'C');

$pdf->SetLeftMargin(32);
$pdf->SetFont('Arial','B',8);
$pdf->Cell(10,7,'',0,1,'C');
$pdf->Cell(6,6,'NO',1,0,'C');
$pdf->Cell(35,6,'TUJUAN',1,0,'C');
$pdf->Cell(23,6,'PEMINJAM',1,0,'C');
$pdf->Cell(35,6,'KENDARAAN',1,0,'C');
$pdf->Cell(28,6,'JAM BERANGKAT',1,0,'C');
$pdf->Cell(28,6,'JAM PULANG',1,1,'C');

$pdf->SetFont('Arial','',8);

$query = mysqli_query($link,
"SELECT some_column
FROM `SOME_TABLE`
WHERE (DATE(some_column) BETWEEN '$keyDateFrom' AND '$keyDateTo')");

$i = 1;
while ($row = mysqli_fetch_array($query)){
    $pdf->Cell(6,6,$i++,1,0,'C');
    $pdf->Cell(35,6,$row['some_column'],1,0);
}
$pdf->Output();
?>

我的意思是,如何让FPDF中的变量API接收到Android的值,这样Android就可以根据查询下载生成的文件了?
我已经尝试在 Postman 上执行此操作 returns 格式正确的 PDF,但在 Android 中不行。

怎么做?什么是替代品?感谢任何帮助。

我成功地从生成的端点 PDF table 检索了 PDF 文件,该文件按预期使用了从 Android 发送的 2 个变量。

我正在使用这些方法作为请求

下载PDF()

    private void downloadPDF() {
        RestApi api = RetroFit.getInstanceRetrofit();
        Call<ResponseBody> printCall = api.getPrint(
                strDateFrom,
                strDateTo
        );
        printCall.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {

                if (response.isSuccessful()) {
                    Toast.makeText(getContext(), "server contacted and has file", Toast.LENGTH_SHORT).show();

                    // The most important part is in below code
                    boolean writtenToDisk = writeResponseBodyToDisk(response.body());
                    Toast.makeText(getContext(), "file download was a success? " + writtenToDisk, Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(getContext(), "Server contact failed ", Toast.LENGTH_SHORT).show();
                }

            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                Toast.makeText(getContext(), "No connection", Toast.LENGTH_SHORT).show();
            }
        });

接口方法:

    @FormUrlEncoded
    @POST("somepath/your_file.php")
    Call<ResponseBody> getPrint(
            @Field("keyDateFrom") String from,
            @Field("keyDateTo") String to
    );

然后 writeResponseBodyToDisk(ResponseBody body) 将响应写入 PDF + 将其保存到设备中

private boolean writeResponseBodyToDisk(ResponseBody body) {
        try {
            File futureStudioIconFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
                    "yourFileName.pdf");

            InputStream inputStream = null;
            OutputStream outputStream = null;

            try {
                byte[] fileReader = new byte[4096];

                long fileSize = body.contentLength();
                long fileSizeDownloaded = 0;

                inputStream = body.byteStream();
                outputStream = new FileOutputStream(futureStudioIconFile);

                while (true) {
                    int read = inputStream.read(fileReader);

                    if (read == -1) {
                        break;
                    }

                    outputStream.write(fileReader, 0, read);

                    fileSizeDownloaded += read;

                    Log.d("TAG", "file download: " + fileSizeDownloaded + " of " + fileSize);
                }

                outputStream.flush();

                return true;
            } catch (IOException e) {
                return false;
            } finally {
                if (inputStream != null) {
                    inputStream.close();
                }

                if (outputStream != null) {
                    outputStream.close();
                }
            }
        } catch (IOException e) {
            return false;
        }
    }

希望我的困惑能对外面的人有所帮助 :P