1. 程式人生 > >spring boot -+- httpclient訪問api -+-下載pdf文件 總結

spring boot -+- httpclient訪問api -+-下載pdf文件 總結

今天專案上做了一個需求,請求別服務的下載介面,但是不能直接去訪問,要寫一個controller中轉一下,為了能做許可權控制;用了springboothttpclient相關技術,實現這個功能分幾步我簡單說一下:

1.寫一個controller(介面) ,給前端請求

2.通過 httpclient 轉發到別的服務的 url

3.獲取httpclient 的流,並寫入到目標路徑(儲存)

4.從 目標路徑獲取檔案流  以完成下載(如果需要的話)

下面來一步一步的說:

1.Controller:控制層就是要把這幾個功能包裝起來咯,看程式碼:

@ApiOperation(value = "獲取pdf", notes = "獲取pdf", consumes = "application/pdf")
    @PostMapping(path = "getPdf")
    public void getPdf(@RequestBody AppScanInput appScanInput, HttpServletResponse response) {      
//預設下載路徑(這個路徑很好理解)
        String classpath = SecurityScanController.class.getClassLoader().getResource("").getPath();
        String saveFilePath = classpath + "pdf/" + appScanInput.getName() + ".pdf";
//判斷檔案是否已經存在,不存在的話,寫httpclient去調下載介面
        File file =new File(saveFilePath);
        if (!file.exists()) {
//從別的服務下載pdf檔案到此服務
            downLoadPdfInSystem(saveFilePath, appScanInput);
        }
//此服務下載到客戶端
        pdfDownload(response, appScanInput);
    }


注意:這裡是從別的服務下載pdf檔案到此服務,,再從此服務下載到客戶端,are you 明白?

上面的註解是swaggerUI的相關注解,注意這個    consumes = "application/pdf",別的沒啥好說2.通過 httpclient 轉發到別的服務的 url

private void downLoadPdfInSystem (String path, AppScanInput appScanInput) {
//別的服務的下載介面url
        String url_down_pdf = UrlConstants.domainUrl_test + UrlConstants.url_down_pdf;
//引數封裝 流的初始化
        Map<String, Object> params = new HashMap<>();
        File f = new File(path);
        InputStream in = null;
        String scanType = appScanInput.getType();
        try {
            params.put("scan_type", scanType);
            params.put("hash", appScanInput.getAa());
//httpclient傳送POST請求,注意看這裡比較重要,doPost是一個方法,我貼在下面了。。。
            HttpEntity httpEntity = HttpUtil.doPost(url_down_pdf, params);
//從返回的httpEntity中獲取輸入流
            in = httpEntity.getContent();
//寫檔案的程式碼,不多說
            OutputStream os = new FileOutputStream(f);
            int bytesRead = 0;
            byte[] buffer = new byte[1024];
            while ((bytesRead = in.read(buffer)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


2.HttpClient傳送請求的方法: 返回的是一個HttpEntity(介面返回的東西都在這裡)

public static HttpEntity doPost(String url, Map<String, Object> param) {
 
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeader("Authorization", ConstPojo.Authorization);
        HttpEntity httpEntity;
        //設定請求和連線超時時間
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(1000 * 60).setConnectTimeout(1000 * 60).build();
        httpPost.setConfig(requestConfig);
        try {
            if (null != param) {
             // 設定引數
                if (CommonUtil.isNotEmptyMap(param)) {
                    UrlEncodedFormEntity encodedFormEntity = new UrlEncodedFormEntity(setHttpParams(param), "UTF-8");
                    httpPost.setEntity(encodedFormEntity);
                }
               
            }
            CloseableHttpResponse response = httpClient.execute(httpPost);
            int statusCode = response.getStatusLine().getStatusCode();
            System.out.println("statusCode:"+statusCode);
            if (statusCode == 200) {
                Header[] allHeaders = response.getAllHeaders();
                httpEntity = response.getEntity();
                
                System.out.println(allHeaders.toString());
                System.out.println(httpEntity.toString());
                return httpEntity;
            } else {
                System.out.println("連線異常。。。");
            }
        } catch (Exception e) {
            // TODO ...
            e.printStackTrace();
        }
        return null;
    }


3.獲取httpclient 的流,並寫入到目標路徑(儲存)

。。。。。。沒東西寫了,第三步的東西,都在第二部的程式碼裡了,pass

4.從 目標路徑獲取檔案流  以完成下載(如果需要的話)

這個就是

pdfDownload(response, appScanInput)這個方法了

public void pdfDownload(HttpServletResponse res, AppScanInput appScanInput) {
        String fileName = appScanInput.getName() + ".pdf";
//設定頭資訊
        res.setHeader("content-type", "application/octet-stream");
        res.setContentType("application/octet-stream");
        res.setHeader("Content-Disposition", "attachment;filename=" + fileName);
        byte[] buff = new byte[1024];
        BufferedInputStream bis = null;
        OutputStream os = null;
        String classpath = SecurityScanController.class.getClassLoader().getResource("").getPath();
        String saveFilePath = classpath + "pdf/" + appScanInput.getName() + ".pdf";
        try {
            os = res.getOutputStream();
            bis = new BufferedInputStream(new FileInputStream(new File(saveFilePath)));
            int i = bis.read(buff);
//防止中文亂碼
            while (i != -1) {
                os.write(buff, 0, buff.length);
                os.flush();
                i = bis.read(buff);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
//        System.out.println("success");
    }


這個檔案下載的程式碼沒什麼說的了,看程式碼應該能看懂的

歡迎各位看官發表看法,互相學習。