android 在浏览器中通过 HTTPS 下载文件

Download file from HTTPS in browser on android

我正在尝试使用 android 移动设备上的浏览器从我的网络应用程序下载文件(在我的情况下,我使用 spring mvc 但是尽管如此,因为我认为这是一个常见问题而不是特定框架)。问题是在 android 设备中使用 chrome 或本机浏览器尝试文件下载永远不会结束,总是出现 In progressqueue (取决于 android 版本,我在下载应用程序时尝试使用 4.1.1 和 5.1.1 )。

我尝试更改涉及的典型 http-headersContent-TypeContent-Disposition 内联或附件,指定 Content-Length 没有成功。

问题是,在 windows 或 linux 中的桌面浏览器中,文件在每种情况下都能正确下载。

我的一些尝试:

  1. 使用org.springframework.http.ResponseEntity:

    @RequestMapping(value= {"/evidenciaDownload"},method = RequestMethod.GET)
    public ResponseEntity<byte[]> getEvidencia(
            @RequestParam(value = "paramsCoded", required = true) String paramsCoded) throws IOException {
    
        String url = configPropsService.getEvidenciaUrlDownload() + URLEncoder.encode(paramsCoded,"UTF-8");
        logger.info("[getEvidencia] Recuperem l'evidencia de : " + url);
    
        // bytes are correct
        byte[] evidencia = downloadFile(url);
    
        HttpHeaders responseHeaders = new HttpHeaders();
        responseHeaders.set("Content-Type", "application/pdf");
        //responseHeaders.set("Content-Disposition","attachment; filename=\"evidencia.pdf\";");
        responseHeaders.set("Content-Disposition","inline; filename=evidencia.pdf");
        responseHeaders.setContentLength(evidencia.length);
        return new ResponseEntity<byte[]>(evidencia, responseHeaders,HttpStatus.CREATED);
    }
    
  2. 直接使用 org.springframework.web.bind.annotation.ResponseBody 到 return 文档 bytes[],以及 produces = "application/pdf" on @RequestMapping:

    @RequestMapping(value= {"/evidenciaDownload"},method = RequestMethod.GET, produces = "application/pdf")
    public @ResponseBody byte[] getEvidencia(
            @RequestParam(value = "paramsCoded", required = true) String paramsCoded) throws IOException {
    
        String url = configPropsService.getEvidenciaUrlDownload() + URLEncoder.encode(paramsCoded,"UTF-8");
        logger.info("[getEvidencia] Recuperem l'evidencia de : " + url);
    
        return downloadFile(url);
    
    }
    
  3. 或者在 javax.servlet.http.HttpServletResponse 输出流中写入文件并指定 headers:

    @RequestMapping(value= {"/documentDownload"},method = RequestMethod.GET)
    public void getDocument(
            @RequestParam(value = "paramsCoded", required = true) String paramsCoded, 
            HttpServletResponse response) throws IOException {
    
        String url = configPropsService.getDocumentsNotficacioUrlDownload() + URLEncoder.encode(paramsCoded,"UTF-8");       
        logger.info("[getDocument] Recuperem el document de : " + url);
    
        // bytes are correct
        byte[] downloadFile = downloadFile(url);
    
        ServletOutputStream outputStream = response.getOutputStream();
    
        int fileLength = IOUtils.copy(new ByteArrayInputStream(downloadFile), outputStream);
        response.setHeader("Content-Disposition","attachment;filename=\"evidencia.pdf\"");
        response.setContentLength(fileLength);
        response.setContentType("application/pdf");
        outputStream.flush();
        outputStream.close();
    }
    

正如我所说,3 个案例在 windows/linux 的桌面浏览器上运行良好,但在 chrome 和 android 设备的本机浏览器上运行良好。

我 post 回答是因为我花了一些时间来寻找我的问题的原因,我希望这可以帮助别人。

问题最终是由部署我的网络应用程序的服务器证书引起的,问题是我的服务器证书是由预生产证书颁发机构颁发的,该证书颁发机构具有使用弱算法 (md5) 散列的中间证书链.此外,它的 CA 来自预生产,因此 surley 它不受 android 信任。

在桌面上,文件下载正确,因为之前下载时我跳过了警告服务器证书问题的页面。

问题是,在 android 上,至少使用 chrome 时,关于服务器证书的警告页面也会出现,我跳过了它,但是在下载管理器中,文件出现在队列中或正在进行中无限期但没有错误消息。我花了一些时间解决这个问题,因为我没有任何错误消息或关于正在发生的事情的指示。

最后,我更改了我的服务器证书,并使用了由受信任的 CA 颁发的正确证书,并且文件开始正确下载问题中指定的三种代码方法。