java,http下载文件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java,http下载文件相关的知识,希望对你有一定的参考价值。

先按顺序下载一个文件(比如大小为1000个字节),当我下载到第100字节时候跳到第500个字节处继续下载,等把500-1000字节下载好了后再返回来下载第100到500字节,最终完成整个文件的下载。

思路是用URLConnecion下方法setRequestProperty("Range", "bytes="+0+"-"+fileSize)请求下载的区间,下载过程中如果想要重新使用setRequestProperty()方法来获取新的下载区间,该怎么做?
现在我的做法是 关闭输入流,再重新 openConnection,setRequestProperty(),重新new 一个RandomAccessFile,用它的seek()方法寻找到新的下载位置后再写入本地文件,这样可以实现功能,但是频繁操作起来下载速度很慢而且容易出现问题,有没有什么好的解决办法。谢谢了

http是流传输,一次请求中你是不能将流截断的,如果想做到你说的只有两种形式:
1、就是你使用的方式,多段读取(其实就是断点续传的原理),多个请求,每个请求请求一部分,如果你觉得效率低可以从两方面优化:
(1)不要用URLConnecion,而使用HttpClient之类的工具包进行请求
(2)使用多线程并发请求,其实就是断点续传了,迅雷就是几个线程一起下嘛
2、只请求一次,请求全部的,将全部流缓存到内存中(byte[]),然后根据你的需要分段截取,写入文件
参考技术A http的下载过程每次连接其实是最耗时间的,你先整个下载下来放到内存中,然后截取你想要的这不行么??

Java35http&response:重定向,文件下载


1.response对象:text/html,重定向(.setStatus,.setHeader)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package com.itheima01.http;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet(urlPatterns = "/MyServlet")
public class MyServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }        
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("服务器被访问了");
//        int i = 1/0; //服务器崩了出异常,没有try catch,状态码500        
        response.setStatus(302); //状态码设置,只有302需要我们手动设置
//      response.setStatus(404); //这样设置状态码是404,servlet优先级高于tomcat,但是访问服务端依旧成功
//        response.getWriter().print("hello response"); //前端网页打印出

        //响应体输出流设置,字节输出流(写)  //待会下载文件案例中使用                
//       ServletOutputStream os = response.getOutputStream();
//       os.write("abc".getBytes()); //01_响应报文.html中点击“访问MyServlet”超链接跳转到显示“abc”的新页面

		//方便输出字符数据,不用转换为字节了,print和write一样
//       PrintWriter writer = response.getWriter();
//       response.getWriter().print("xx");  
    }
}

请求报文分get和post两种,在响应报文里看到了非servlet设置的内容,那就是tomcat设置的。将前端改为href="/MyServlet123",则会出现404。servlet关了,tomcat自动设置为500状态码。

如下体中hello response长度一共为Content-Lenth为14,头中GMT格林位置需+8小时为东八区北京时间。如下行和头都是tomcat默认自动设置,体是我们servlet手动设置。想修改状态码,需要在servlet(对我们暴露的小程序)中修改。
在这里插入图片描述
在这里插入图片描述
如下响应头分四种(蓝色字),如下简易API等同上行。
在这里插入图片描述
在这里插入图片描述
如下点击后,5秒后跳转到百度
在这里插入图片描述

package com.itheima02.header;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(urlPatterns = "/RefreshAndTypeServlet")
public class RefreshAndTypeServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("服务器被访问了");
//        response.setHeader("refresh","5;http://www.baidu.com");

//11111111111111111111111111111111111111111111111111111111111111111111111111111111111111
        /*
        *   问题: 响应体中文乱码 。request.setCharacterEncoding("utf-8");
        *   原因:  编码: 服务器(utf-8 : servlet:因为在servlet里写的"哈哈",idea右下角显示utf-8)
        *          解码: 浏览器(iso-8859-1 : tomcat默认设置如下行)     
  // response.setHeader("content-type","text/plain");  //在Response Headers(浏览器F12看出)中多出tomcat默认设置(不加这行不显示):Content-Type: text/plain;charset=ISO-8859-1

        *   解决: servlet中手动设置覆盖tomcat默认设置
        *
        *    windows系统:      txt        html          jpg          avi     ...
        *    早期MIMEType :  text/plain   text/html     image/jpeg (tomcat解压包中web.xml中有对应说明)
        */
//        response.setHeader("content-type","text/plain;charset=utf-8"); //新页面显示 <h1>哈哈</h1>
//        response.setHeader("content-type","text/html;charset=utf-8");  //点击网页上RefreshAnd..跳转新页面显示 哈哈
        response.setContentType("text/html;charset=utf-8"); //setContentType是简易API,同上一行
        response.getWriter().print("<h1>哈哈</h1>"); 
    }
}

因为重定向不是一次请求链,所以超过域对象,不能用request传递数据。ZhouServlet收不到人事的msg,能收到ShiServlet的response.setHeader(…/ZhouServlet?msg=…)。
在这里插入图片描述
在这里插入图片描述

package com.itheima03.redirect;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(urlPatterns = "/ShiServlet")
public class ShiServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        doGet(request, response);
    }        
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 接收请求
        String msg = request.getParameter("msg");
        System.out.println("shi:" + msg);
        //2. 重定向
        response.setStatus(302);
        response.setHeader("location","/ZhouServlet?msg=xx"); //不写?msg=xx,ZhouServlet就收不到msg,写了就能收到
    }
}
package com.itheima03.redirect;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(urlPatterns = "/ZhouServlet")
public class ZhouServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 接收请求
        String msg = request.getParameter("msg");
        System.out.println("zhou:" + msg);
        //2. 业务处理
        System.out.println("这个哥们还不错");
        //3. 响应数据
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().print("这个哥们还可以,大约3K");
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如下浏览器F12,第二行没有带参数,拿不到msg。
在这里插入图片描述
前面登陆成功请求转发到成功.html页面,失败…。用请求转发不合适,因为没有传递数据,应该用重定向。请求转发一次请求,地址指向第一次访问位置如下所示(网址阅读性太差,实际页面应该为localhost:8080/success.html)。
在这里插入图片描述
如下红框用重定向,登陆失败逻辑错误,之后再改。
在这里插入图片描述
如下重定向,第一次请求收到302。
在这里插入图片描述
在这里插入图片描述

2.文件下载:request/response

首先服务器要有文件,在网络编程做过文件上传:【Java31】。在servlet里写代码覆盖tomcat默认设置。
在这里插入图片描述

//02文件下载.html
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
 <!--方案A:浏览器打开此网页点击后自动下载的话,说明tomcat默认设置,因为servlet一个字没写-->
   <!-- <a href="dir/1.zip">1.zip</a> <br>   
    <a href="dir/2.exe">2.exe</a> <br>
    <a href="dir/3.txt">3.txt</a> <br>
    <a href="dir/4.jpg">4.jpg</a> <br>-->

   <a href="/DownloadServlet?file=1.zip">1.zip</a> <br>
   <a href="/DownloadServlet?file=2.exe">2.exe</a> <br>
   <a href="/DownloadServlet?file=3.txt">3.txt</a> <br>
   <a href="/DownloadServlet?file=4.jpg">4.jpg</a> <br>
</body>
</html>
package com.itheima04.down;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;

@WebServlet(urlPatterns = "/DownloadServlet")
public class DownloadServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String file = request.getParameter("file"); // 拿到1.zip之类
        //1. 告诉浏览器如何处理文件
        response.setHeader("content-disposition","attachment;filename=x" + file); //下载以x命名
        
        //2. 读取服务器本地文件,写出浏览器
            //TODO: 绝对路径 等会要改成 相对路径
            /*
            *   以前java工程: web/dir/文件(相对路径,里面是1.zip,2.exe等需下载的文件)
            *        web工程: main方法在tomcat里,造成和java工程相对路径不一样
            */
//   FileInputStream fis = new FileInputStream("E:/mywork/IdeaProjects/class897/web-day03/web/dir/" + file);

       //ServletContext servletContext1 = this.getServletContext(); //this是当前的servlet对象:servlet.getServletContext()  //同下一行
        ServletContext servletContext = request.getServletContext(); //request小域对象可获取ServletContext大域对象 
        String realPath = servletContext.getRealPath("dir/" + file); //绝对路径换成相对路径 
                
        FileInputStream fis = new FileInputStream(realPath);
        ServletOutputStream os = response.getOutputStream();
        int length;
        byte[] buffer = new  byte[1024];
        while((length = fis.read(buffer)) != -1){
            os.write(buffer,0,length);
        }
        fis.close();
        os.close();
        System.out.println("文件下载完毕");
    }
}

响应体交给浏览器,浏览器自动下载。
在这里插入图片描述
linux没有盘符,所以不能用绝对路径,不好部署。如下artifacts指整个项目,运行的是如下蓝字编译的内容(黄色文件夹),只要获得web_war_exploded文件夹就能得到其他文件相对路径。用serlvetContext = web_war_exploded文件夹路径(exploded部署意思,如下红线),如下右边servletContext是生命周期最长的域对象,所以可以将数据传到服务器任何地方。

request除了作为域对象还有本职工作即获取请求数据,servletContext很像连接池(连接池一个就够),服务器没关,连接池不消毁。servletContext生命周期和web应用一样长,所以也叫application应用,环境参数如相对路径。request和session两个域对象用的最多,pageContext太短,servletContext太长。重定向不能通过request传递数据,可以用servletContext传递数据,但是一般也不这么做,servletContext占用内存大。
在这里插入图片描述
上图灰色WEB-INF文件夹中添加lib文件夹里放druid-1.0.9.jar包并右击add as library(【Mysql3】),点乌龟运行tomcat后,会生成黄色lib文件夹。黄色classes文件夹里代码不能直接访问,用web.xml或用注解建立映射关系访问:WEB-INF下是浏览器无法直接访问,通过建立映射,url访问,由tomcat访问。
在这里插入图片描述
热更新不做编译,新增类必须停下来。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

以上是关于java,http下载文件的主要内容,如果未能解决你的问题,请参考以下文章

用JAVA下载HTTP文件时遇到问题

HTTP文件下载JAVA后台的实现

使用Java通过http下载文件

java通过http方式下载文件

Java实现Http文件下载实例

java如何实现文件上传和下载的功能