JAVA实现文件的上传和下载

目录

一、文件的上传和下载的作用

什么是文件上传?

文件的下载及需求

为什么使用文件上传?

二、文件上传

文件上传的关键

不同的框架提供了不同的获取输入流的方式--Servlet上传案例

文件上传细节

 存储位置

文件上传问题-目录分离

三、文件下载

下载的关键

超链接下载问题分析

Servlet下载

四、文件上传及下载演示

运行结果

 关于下载时乱码问题


一、文件的上传和下载的作用

什么是文件上传?

要将客户端(浏览器)大数据存储到服务器端,不将数据直接存储到数据库中,而是要将数据存储到服务器所在的磁盘上,这就要使用文件上传。

文件的下载及需求

广义上,任何从服务器端获取数据的过程都属于文件下载,默认情况下由浏览器打开展示。狭义的文件下载,将从服务器端获取的数据以附件的形式保存到本地,其实就是将服务器端的资源通过io流写回到浏览器端。

文件下载需求:

  1. 页面显示超链接

  2. 点击超链接后弹出下载提示框

  3. 完成图片文件下载

为什么使用文件上传?

通过文件上传,可以将浏览器端的大数据直接保存到服务器端。不将数据保存到数据库中,而是保存到服务器磁盘上,这样减少了数据库服务器的压力,对数据的操作更加灵活

二、文件上传

文件上传对请求的前提:

  1. 请求方式:提供form表单,method必须是post

  2. 数据类型:表单必须设置enctype="multipart/form-data"

  3. 控件:需要使用控件< input type="file" name="file"> 控件必须有名称

表单编写:

<form action="upload" method="post" enctype="multipart/form-data">
        <input type="file" name="file">
        <button>上传</button>
    </form>

文件上传的关键

上传文件在服务器上的目录一般已固定,只需要获取了输入流,就可以完成上传任务。上传文件在客户端的路径由用户指定

服务器端处理:

通过request对象,获取InputStream, 可以将浏览器提交的所有数据读取到,解析请求正文的每部分的内容

不同的框架提供了不同的获取输入流的方式--Servlet上传案例

Servlet提供了Part对象获取输入流。下面演示的是将文件上传到D:/upload/目录下保存。

package com.bib.servlet;

import com.bib.utils.IOUtils;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

@MultipartConfig
@WebServlet("/upload")
public class UploadServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取上传到服务器的临时文件对象
        Part part = req.getPart("file");
        //获取上传的文件名 
        String submittedFileName = part.getSubmittedFileName();
        //获取临时文件的输入流
        InputStream inputStream = part.getInputStream();
        //构建文件输出流
        FileOutputStream fileOutputStream = new 
        FileOutputStream("D:/upload/"+submittedFileName);
        //IO流读写操作
        IOUtils.readAndWrite(inputStream, fileOutputStream);
        //跳回首页
        resp.sendRedirect("/index");
    }
}

文件上传细节

文件重名问题

每一个客户端都可以进行文件上传操作,那么当我们上传的文件过多,一定会出现同名的文件,那么在服务器端只能保存一个,对于这个问题,我们在上传文件时,就需要考虑文件重名问题

解决方案

一般情况下,对于上传文件,为了保证不重名,会给文件起一个随机名

  • 一种方案是使用uuid

  • 一种方案是使用毫秒值

 存储位置

上传操作文件存储位置分析

本质就是上传的文件是否允许浏览器端直接访问。例如:商品添加时需要一个图片,这个图片一定是可以直接被浏览器端访问的。

解决方案

  • 允许被浏览器端访问:     

 放置在Web目录下,但不能是WEB-INF或META-INF下其及子目录下

  • 不允许被浏览器端访问:

工程下:放置在WEB-INF或META-INF及其子目录下

文件上传问题-目录分离

上传操作文件过多问题分析

当我们上传文件过多,并且保存在同一个目录下时,我们就需要考虑怎样处理它们,因为一个目录下文件过多,不仅降低性能,操作时也不方便。

解决方案

为了防止同一个目录下方上传文件数量过多

  • 按照上传时间进行目录分离 (周、月 )

  • 按照上传用户进行目录分离 ----- 为每个用户建立单独目录

  • 按照固定数量进行目录分离 ------ 假设每个目录只能存放3000个文件 ,每当一个目录存满3000个文件后,创建一个新的目录

  • 按照唯一文件名的hashcode 进行目录分离

三、文件下载

下载的关键

下载是从服务器固定目录获取文件,输入流可知,输出路径由用户定义,因此关键是创建输出流。

超链接下载问题分析

  • 超链接指向的资源如果能够被浏览器解析,则在浏览器中展示,如果不能解析,则弹出下载提示框。不满足需求

  • 任何资源都必须弹出下载提示框

  • 使用响应头设置资源的打开方式

  • content-disposition:attachment;filename=xxx

Servlet下载

Servlet提供了ServletOuputStream作为文件下载的输出流。

package com.bib.servlet;

import com.bib.utils.IOUtils;
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;
import java.net.URLEncoder;

@WebServlet("/download")
public class DownloadServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String name = req.getParameter("name");
        FileInputStream fileInputStream = new FileInputStream("d:/upload/" + name);
        int len = fileInputStream.available();
        ServletOutputStream outputStream = resp.getOutputStream();
        //1.告诉浏览器文件类型是二进制
        resp.setContentType("application/octet-stream");
        //2.告诉浏览器文件名
        resp.setHeader("content-disposition","attachment;filename="+ URLEncoder.encode(name,"utf-8"));
        //3.告诉浏览器文件大小
        resp.setContentLength(len);
        //IO流读写操作
        IOUtils.readAndWrite(fileInputStream,outputStream);
    }
}

四、文件上传及下载演示

IndexServlet.java代码

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.File;
import java.io.IOException;

@WebServlet("/index")
public class IndexServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //创建File对象,指向文件上传的目录
        File file = new File("D:/upload");
        //获取该目录下的文件列表
        String[] list = file.list();
        //将文件列表存到request作用域
        req.setAttribute("list", list);
        //转发到index.jsp
        req.getRequestDispatcher("index.jsp").forward(req, resp);
    }
}

index.jsp页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
  <head>
    <title>文件列表</title>
  </head>
  <body>
  <%--文件显示--%>
  <h1>文件列表</h1>
  <c:forEach items="${list}" var="f">
    <a href="download?name=${f}">${f}</a><br>
  </c:forEach>
  </body>
</html>

运行结果

首先访问upload.jsp页面,进行文件上传

点击选择文件,选择本地的任意文件

 ​​​​​

 点击上传,文件上传至D:/upload/目录下,跳转至index.jsp页面显示

 查看D:/upload文件夹

点击文件下载

在下载路径查看文件

 

至此完成 简单的文件的上传与下载

 关于下载时乱码问题

对于下载时,我们在显示下载文件名称时,如果包含了中文,就可能出现乱码问题,出现的原因,是对于不同的浏览器,它们在处理下载文件时的编码不一致,ie浏览器使用的是utf-8编码,而firefox浏览器使用的是base64编码

解决思路:

  1. 获取客户端使用的浏览器版本信息

  2. 根据不同的版本信息,设置文件名的编码方式不同
        //1.告诉浏览器文件类型是二进制
        resp.setContentType("application/octet-stream");
        //2.告诉浏览器文件名
        resp.setHeader("content-disposition","attachment;filename="+ URLEncoder.encode(name,"utf-8"));
        //3.告诉浏览器文件大小
        resp.setContentLength(len);

  • 11
    点赞
  • 130
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
文件上传: 1. 创建一个表单,包含一个文件上传的input标签: ```html <form action="upload" method="post" enctype="multipart/form-data"> <input type="file" name="file"/> <input type="submit" value="上传"/> </form> ``` 2. 在服务器端创建一个Servlet处理上传文件: ```java public class UploadServlet extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取上传文件 Part filePart = request.getPart("file"); String fileName = filePart.getSubmittedFileName(); InputStream fileContent = filePart.getInputStream(); // 将文件写入磁盘 OutputStream out = new FileOutputStream(new File("/path/to/uploaded/files/" + fileName)); IOUtils.copy(fileContent, out); out.close(); } } ``` 文件下载: 1. 在服务器端创建一个Servlet处理下载请求: ```java public class DownloadServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取要下载文件路径 String filePath = "/path/to/downloaded/files/file.txt"; File downloadFile = new File(filePath); // 设置响应头 response.setContentType("application/octet-stream"); response.setContentLength((int) downloadFile.length()); response.setHeader("Content-Disposition", "attachment;filename=\"" + downloadFile.getName() + "\""); // 将文件写入输出流 FileInputStream in = new FileInputStream(downloadFile); OutputStream out = response.getOutputStream(); IOUtils.copy(in, out); in.close(); out.close(); } } ``` 2. 在前端页面添加一个下载链接: ```html <a href="download">下载文件</a> ``` 其中,download是下载Servlet的映射路径。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值