首页 新闻 会员 周边 捐助

手机端如何下载pdf文件

0
悬赏园豆:100 [已解决问题] 解决于 2019-12-04 13:37

首先说下场景,pdf文件在linux根目录下比如/nasdata/xxx.pdf,所以前端无法直接访问了,我采用的servlet请求后返回给前端文件流的形式,但试了很多方法PC端能正常,而手机端点击后,不知道是不是被拦截还是什么,显示的未知文件。
用不太来,这个文本,希望大佬说下怎么才能在手机端下载?(必须那个路径,这个刚好是公司的类似外接硬盘)
servlet中post请求代码如下:
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp){
// String src=req.getSession().getServletContext().getRealPath("/");
resp.setStatus(HttpServletResponse.SC_OK);
resp.setContentType("application/pdf;charset=UTF-8");
// resp.setContentType("multipart/form-data");
resp.setHeader("Content-Disposition", "attachment;filename=a.pdf");
String path = req.getParameter("path");
File w2 = new File(path);

    logger.info("pdf path:" + w2.getPath());
    FileInputStream fs;
    try {
        fs = new FileInputStream(w2);
        BufferedInputStream bs = new BufferedInputStream(fs);
        PrintWriter outW = resp.getWriter();
        byte buffBytes[] = new byte[3072];
        /**
         * 这里的新建的byte数组的大小必须是24的倍数,原因看下base64的原理
         **/
        int read = 0;
        while ((read = bs.read(buffBytes)) != -1) {
            String strTemp = new sun.misc.BASE64Encoder().encode(Arrays
                    .copyOfRange(buffBytes, 0, read));
            outW.print(strTemp);
        }
        if (bs != null) {
            try {
                bs.close();
            } catch (IOException e1) {
                logger.error(e1.getMessage(), e1);
            }
        }
    } catch (Exception e) {
        logger.info("pdf出错");
        logger.error(e.getMessage(), e);
    }

}

js中请求:
$.ajax({
type: "post",
async: false,
url: projectName+"/PdfDownloadServlet?path="+path,
success: function (data) {
// var blob = new Blob([base64toBlob(data)], {type: "application/pdf;charset=utf-8"});
// saveAs(blob, "CF1002.pdf");
let URL = base64toBlob(data);
var reader = new FileReader();
  reader.readAsDataURL(URL);
alert(URL);
  reader.onload = function (e) {
    // 兼容IE
    if (window.navigator.msSaveOrOpenBlob) {
      var bstr = atob(e.target.result.split(",")[1]);
      var n = bstr.length;
      var u8arr = new Uint8Array(n);
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
      }
      var blob = new Blob([u8arr]);
      window.navigator.msSaveOrOpenBlob(blob,'asd.pdf');
    } else {
      // 转换完成,创建一个a标签用于下载
      var a = document.createElement('a');
      a.download = 'asd.pdf';
      a.href = e.target.result;
      a.setAttribute("id", "export")
      document.getElementById("purchaseManage").append(a); // 修复firefox中无法触发click
      a.click();
      document.getElementById("export").remove();
  }
}

    },error: function(e){  
        // 进入到了error,成功打印出信息,也刷新了list,
        // 但是edit的弹窗页面和询问框没有正确关闭
        console.log(e);
        alert(e);
    }
});
代码可乐的主页 代码可乐 | 初学一级 | 园豆:139
提问于:2019-12-04 10:02
< >
分享
最佳答案
0

url: projectName+"/PdfDownloadServlet?path="+encodeURIComponent(path) 试试编码一下。

收获园豆:100
Timetombs | 老鸟四级 |园豆:3959 | 2019-12-04 10:22

好的我试试看

代码可乐 | 园豆:139 (初学一级) | 2019-12-04 10:27

还是一样的,传回去路径是正常的

代码可乐 | 园豆:139 (初学一级) | 2019-12-04 10:33

@代码可乐: 下载一般不都是直接一个a 链接触发一个get请求就可以了,你这用一个post请求干什么?

Timetombs | 园豆:3959 (老鸟四级) | 2019-12-04 10:40

@代码可乐: 还有一点不理解,下载文件直接输出byte就可以了,为什么要转成base64?

Timetombs | 园豆:3959 (老鸟四级) | 2019-12-04 10:42

@blackheart: 因为文件在linux根路径下啊,公司的项目的外接硬盘吧,用来放大文件这些吧,项目路径下要是能放早好了。。。。

代码可乐 | 园豆:139 (初学一级) | 2019-12-04 10:43

@代码可乐: 和文件放在哪有什么关系?没关系啊

Timetombs | 园豆:3959 (老鸟四级) | 2019-12-04 10:45

@blackheart: 大佬可以给下思路吗?后端返回什么形式的数据,前端拿什么接收并转换?

代码可乐 | 园豆:139 (初学一级) | 2019-12-04 10:47

@代码可乐: 不用转换啊,后端直接把fs = new FileInputStream(w2);的fs写入到httpresponse的相应流即可。

Timetombs | 园豆:3959 (老鸟四级) | 2019-12-04 11:11

@blackheart: 好的我试试

代码可乐 | 园豆:139 (初学一级) | 2019-12-04 11:15

@代码可乐:

protexted void doGet(HttpServletRequest req, HttpServletResponse resp) {
  String fileName = req.getParameter("fileName");
  resp.setStatus(HttpServletResponse.SC_OK);
  resp.setContentType("application/pdf;charset=UTF-8");
  resp.setHeader("Content-Disposition", "attachment;filename=a.pdf");

  File file = new File("/你的文件存放目录/" + fileName);
  try (InputStream fileInputStream = new FileInputStream(file);
       OutputStream httpOutputStream = resp.getOutputStream();) {
    int length = 0;
    byte[] buffer = new byte[4096];
    while ((length = fileInputStream.read(buffer)) != -1) {
      httpOutputStream.write(buffer, 0, length);
    }
    resp.setHeader("Content-Length", String.valueOf(file.length()));
  } catch (Exception e) {
    logger.error(e.getMessage(), e);
  }
}
Timetombs | 园豆:3959 (老鸟四级) | 2019-12-04 11:19

@blackheart: 我先试试哈谢谢大佬

代码可乐 | 园豆:139 (初学一级) | 2019-12-04 13:37

大佬前端接收到data为空,是不是后端哪里有问题

代码可乐 | 园豆:139 (初学一级) | 2019-12-04 14:23

@代码可乐: 还要前端发起ajax干什么?直接一个a标签或者window.open(url)就可以了啊。 对了url改成get方式访问。

Timetombs | 园豆:3959 (老鸟四级) | 2019-12-04 14:26

@代码可乐: 还有,你这样传递path直接下载太不安全了,相当于把你的服务器的所有目录的所有文件数据拱手想让,肯定不能通过参数来随意指定文件路径的。 上面代码给你修改了一下,起码限定一下目录。参数上只传递文件名即可。

Timetombs | 园豆:3959 (老鸟四级) | 2019-12-04 14:34

@blackheart: 前端我是按钮click时间里写直接window.open(项目名/servlet名?参数)?我再看下这个pdf好像不能正常打开

代码可乐 | 园豆:139 (初学一级) | 2019-12-04 14:49

浏览器直接访问完整的url呢?

Timetombs | 园豆:3959 (老鸟四级) | 2019-12-04 14:53

@blackheart:可以直接访问,但是看了那个pdf是0kb

代码可乐 | 园豆:139 (初学一级) | 2019-12-04 14:59

@代码可乐: 设置content-length后就可以了,上面的代码我给你更新过了。

Timetombs | 园豆:3959 (老鸟四级) | 2019-12-04 15:21

@blackheart: 可以了感谢大佬

代码可乐 | 园豆:139 (初学一级) | 2019-12-04 15:29
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册