今天项目上做了一个需求,请求别服务的下载接口,但是不能直接去访问,要写一个controller中转一下,为了能做权限控制;用了springboot,httpclient相关技术,实现这个功能分几步我简单说一下:

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");
    }

 

这个文件下载的代码没什么说的了,看代码应该能看懂的

 

欢迎各位看官发表看法,互相学习。