Hbuilder打包web项目为app时,下载文件失效,下载出现问题解决

问题描述:我是将我的web项目使用hbuilder打包成apk安装在手机上,然后使用下载功能的时候,跳转到报错页面,但是在pc端浏览器和手机浏览器上没有问题,报错页面如下:

在这里插入图片描述
其实这是因为使用a链接发送请求下载文件时,默认会有短暂跳转到空白页的行为,但是我后面使用form,以及iframe方式下载,虽然可以下载,但是我在手机上找不到文件位置,这样,软件又需要自动打开刚才下载的文件,不然用户找起来很费劲。
于是,我搜集了很多资料终于完美解决了这个问题。
思路:在下载文件,如点击a链接时,让它跳转到外部浏览器上,使用外部浏览器进行托管下载,这样,能使得下载功能达到最大人性化。
首先介绍一个api:

plus.runtime.openURL(url)
//url:使用外部浏览器让用户下载的页面地址
//如http://101.40.131.45:8080/downfile/
//这个plus是Hbuilder提供的第三方插件,只有在打包的app上面才有效
//在pc端的浏览器上是不存在的,所以提供下方代码,判断当前设备类型
          //检测用户当前的设备
          var system = {
    
    
                win: false,
                mac: false,
                xll: false,
                ipad:false
            };
            //检测平台
            var p = navigator.platform;
            
            system.win = p.indexOf("Win") == 0;
            system.mac = p.indexOf("Mac") == 0;
            system.x11 = (p == "X11") || (p.indexOf("Linux") == 0);
            system.ipad = (navigator.userAgent.match(/iPad/i) != null)?true:false;
            //当用户的设备是win时,
            if(system.win){
    
    
            	//xxxxx
            }else{
    
    
				//xxxxxx
			}

下面是我使用的代码,真实项目中的:

//html标签:
///down/downProjFile/1中的1是要下载文件存在数据库中的id号
//其它字段还有文件的存储路径等,反正通过id号,我的后台就能够知道下载哪个文件
<a href="/down/downProjFile/1" fileid="1" class="downABtn btn btn-warning">下载</a>

//js代码:
 $(".downABtn").click(function () {
    
    
            var system = {
    
    
                win: false,
                mac: false,
                xll: false,
                ipad:false
            };

            //检测平台
            var p = navigator.platform;

            system.win = p.indexOf("Win") == 0;
            system.mac = p.indexOf("Mac") == 0;
            system.x11 = (p == "X11") || (p.indexOf("Linux") == 0);
            system.ipad = (navigator.userAgent.match(/iPad/i) != null)?true:false;
            if(system.win){
    
    
                return true;
            }
            const fileid = $(this).attr("fileid");
            plus.runtime.openURL('https://101.210.165.250:8443/wzq-0.0.1-SNAPSHOT/down/downFilePage/' + fileid);
		
		   //阻止a链接的默认行为
            return false;
        })

Java的后台代码:(根据你使用的语言进行对比即可)

@Controller
@RequestMapping("/down")
public class DownLoadController {
    
    

    //存储文件的目录
    @Value("${system.filePath}")
    private String filePath;

    @Autowired
    private ProjFileService projFileService;

	//跳转到下载页面的请求,即是使用plus跳转的请求
    @RequestMapping("/downFilePage/{fileId}")
    public String downFilePage(@PathVariable("fileId")Integer fileId, Map<String, Object> map){
    
    
        map.put("fileId", fileId);
        return "proj/downFilePage";
    }

    //下载文件的请求
    @RequestMapping("/downProjFile/{fileId}")
    public void downProjFIle(@PathVariable("fileId") Integer fileId, HttpServletResponse res) throws Exception{
    
    
        ProjFile projFile = projFileService.getProjFileById(fileId);
        String fileName = projFile.getName();
        //下面的代码是通用的
        res.setHeader("content-type", "application/*");
        res.setContentType("application/*");
        res.setHeader("Content-Disposition", "attachment; filename=" + new String(fileName.getBytes("utf-8"), "iso8859-1"));
        byte[] buff = new byte[1024];
        BufferedInputStream bis = null;
        OutputStream os = null;
        try {
    
    
            os = res.getOutputStream();
            //这里的 filePath + fileName 可以改成你文件存储的位置
            bis = new BufferedInputStream(new FileInputStream(
                    new File(filePath + fileName )));
            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();
                }
            }
        }
    }
}

下载页面我用的thymeleaf,做的很简单,只有一个确认下载按钮,代码如下:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<script th:src="@{/webjars/jquery/3.0.0/jquery.js}" type="text/javascript"></script>
<link rel="stylesheet" th:href="@{/asserts/css/bootstrap.min.css}" />
<body>
<center>
    <a th:href="@{
     
     '/down/downProjFile/' + ${fileId}}" class="btn btn-warning btn-lg" id="downABtn">确认下载</a>
</center>
</body>
</html>

页面效果:(这里的页面就是使用外部浏览器打开的)
在这里插入图片描述
为什么要把下载文件和转到下载页面的两个请求放到独立的Controller中,因为我项目中涉及到登录,有拦截器配置,放到独立的Controller中容易配置,打开外部浏览器即可下载,不需要用户再进行登录操作。

猜你喜欢

转载自blog.csdn.net/qq_42458992/article/details/107057069