欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【文件上传和下载教科书】分分钟掌握JavaWeb中文件上传和下载(学习总结)

程序员文章站 2022-04-24 12:38:06
...

前言

抽出时间,我会将文章系统的整理到GitHub上。目前已经整理好了JavaSE阶段的知识章节内容。我会持续的向GitHub中添加各类知识点。欢迎大家来我的GitHub查房!还请客官们给一个Star!GitHub中有我微信,可以添加我微信,我们在学习交流群中不见不散!
GitHub地址:https://github.com/Ziphtracks/JavaLearningmanual

一、文件上传

1.1 文件上传的核心思想

将电脑中的本地文件根据网络协议并通过IO流的读写传递到另一台电脑(服务器)中储存!

1.2 文件上传中JSP的三要素

  • 表单提交方式必须是post(method=post)
    • 原因get提交方式只能提交小文件,而给文件上传做了很大的限制;post可以提交大文件
  • 表单中需要文件上传项(<input type=“file”>)
    • 既然要实现文件上传,那么就需要文件上传按钮和上传文件框
  • 表单设置请求体格式(enctype=multipart/form-data)
    • 设置表单的MIME编码。默认情况编码格式是application/x-www-form-urlencoded,不能用于文件上传。只有设置了multipart/form-data,才能完整的传递文件数据
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>文件上传</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/upload" method="post" enctype="multipart/form-data">
    文件描述:<input type="text" name="description"><br>
    <input type="file" name="file"><br>
    <br>
    <button type="submit">上传</button>
</form>
</body>
</html>

1.3 上传文件核心jar包

此jar包可以自行下载,也可以在我的github中下载,我在github上的中也整理出来的jar包库!

  1. commons-fileupload-1.4.jar

  2. commons-io-2.6.jar

1.4 文件上传的细节处理

1.4.1 文件名重复覆盖问题

为了防止客户端传向服务器的文件名称一致发生文件的覆盖,我们需要将文件名称唯一化!

// 文件名称保证唯一性(文件名称 = 当前时间毫秒值 + 文件名称)
fileName = System.currentTimeMillis() + "-" + fileItem.getName();
1.4.2 使用目录分离算法存储文件

为了防止将大量文件存储在服务器的一个文件夹中,我们需要目录使用Hash的目录分离算法来存储文件(类似给存储文件的文件夹做了负载均衡)

注意:在后面的没有使用该工具类实现,而且嵌入到了Servlet中

【文件上传和下载教科书】分分钟掌握JavaWeb中文件上传和下载(学习总结)

package com.mylifes1110.java.utils;

import java.io.File;

/**
 * 目录分离算法
 */
public class UploadUtils {

    // 为防止一个目录下文件过多,使用hash算法打散目录
    public static String newFilePath(String basePath, String fileName) {

        // 获取文件hash码
        int hashCode = fileName.hashCode();

        // 使用hash码进行与运算并生成二级目录
        int path2 = hashCode & 15;

        // 使用hash码进行与运算并生成三级目录
        int path3 = (hashCode >> 4) & 15;

        // 将一级、二级、三级目录拼接并生成完整目录路径
        String path = basePath + File.separator + path2 + File.separator + path3;
        File   file = new File(path);

        // 创建Hash打散后的多级目录
        if (!file.exists()) {
            file.mkdirs();
        }

        // 返回完整目录路径
        return path;
    }
}
1.4.3 文件上传jar包API

ServletFileUpload:核心解析类

方法 描述
parseRequest(HttpServletRequest request) 解析请求,并获取相关文件项
setHeaderEncoding(String encoding) 解决中文文件名乱码

FileItem:文件项

方法 描述
boolean isFormField() 返回为true为普通字段。返回为false为文件
String getFieldName() 获取表单字段
String getString(String encoding) 根据指定编码格式获取字段值
String getName() 获取上传文件名称
InputStream getInputStream() 获取上传文件对应的输入流

二、文件下载

2.1 文件下载的核心思想

将服务器中的文件根据网络协议并通过IO流读取传递到另外一台电脑中并储存!

2.2 文件下载的两种格式

  • 超链接
    • 如果浏览器支持这个格式的文件.可以在浏览器中打开.如果浏览器不支持这个格式的文 件才会提示下载
  • 手动编写代码的方式下载

2.3 手动编写代码方式的三要素

  • 设置响应对象的媒体类型
  • 设置下载窗口
    • 设置下载窗口是通过响应对象对响应头的操作(“Content-Disposition”)
  • IO流读写文件

2.4 文件下载的细节处理

2.4.1 解决下载文件后名称中文乱码问题

各种浏览器的编码解码都是不同的,所以不同的浏览器对文件名称的编码方式不同,我们要以Google浏览器为代表的是以utf-8对文件名称进行编码,其他的一些浏览器以base64对文件名称进行编码,这就需要判断响应头中使用的浏览器的类型(User-Agent)

/**
 * base64编码
 *
 * @param fileName 文件名称
 * @return 返回一个处理编码后的文件名称
 */
public String base64EncodeFileName(String fileName) {
    BASE64Encoder base64Encoder = new BASE64Encoder();

    try {
        return "=?UTF‐8?B?" + new String(base64Encoder.encode(fileName.getBytes("utf-8"))) + "?=";
    } catch (Exception e) {
        e.printStackTrace();

        throw new RuntimeException(e);
    }
}
		/**
         * 不同的浏览器对文件名称的编码方式不同,以google浏览器为代表的是以utf-8对文件名称进行编码
         * 其他的一些浏览器以base64对文件名称进行编码
         * 判断使用的浏览器的类型User-Agent
         */
        String userAgent   = request.getHeader("User-Agent");
        String newFileName = null;

        if (userAgent.contains("Chrome")) {

            // Google浏览器以utf-8进行编码
            newFileName = URLEncoder.encode(fileName, "utf-8");
        } else {

            // 其他浏览器以base64进行编码
            newFileName = base64EncodeFileName(fileName);
        }

        // Google浏览器:new String(fileName.getBytes("utf-8"), "ISO8859-1")
        // 注释中的Google浏览器的代码只针对Google浏览器,不具有普适性!
        // response.setHeader("Content-Disposition", "attachement;filename=" + new String(fileName.getBytes("utf-8"), "ISO8859-1"));
        response.setHeader("Content-Disposition", "attachement;filename=" + newFileName);

三、文件上传和下载案例

3.1 项目结构

【文件上传和下载教科书】分分钟掌握JavaWeb中文件上传和下载(学习总结)

3.4 项目所用jar包

【文件上传和下载教科书】分分钟掌握JavaWeb中文件上传和下载(学习总结)

3.3 项目代码演示

库表操作
create table tb_uploadfiles
(
    id          int auto_increment
        primary key,
    fileName    varchar(200) null,
    filePath    varchar(200) null,
    description varchar(200) null
);
c3p0.properties文件
c3p0.driverClass=com.mysql.jdbc.Driver
c3p0.jdbcUrl=jdbc:mysql://localhost:3306/temp?useUnicode=true&characterEncoding=utf-8
c3p0.user=root
c3p0.password=123456
c3p0连接池工具类
package com.mylifes1110.java.utils;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class DBUtils {
    private static ComboPooledDataSource dataSource;

    static {
        dataSource = new ComboPooledDataSource();
    }

    public static ComboPooledDataSource getDataSource() {
        return dataSource;
    }
}
Files实体类
package com.mylifes1110.java.bean;

public class Files {
    private Integer id;
    private String  fileName;
    private String  filePath;
    private String  description;

    public Files() {}

    public Files(Integer id, String fileName, String filePath, String description) {
        this.id          = id;
        this.fileName    = fileName;
        this.filePath    = filePath;
        this.description = description;
    }

    @Override
    public String toString() {
        return "Files{" + "id=" + id + ", fileName='" + fileName + '\'' + ", filePath='" + filePath + '\''
               + ", description='" + description + '\'' + '}';
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public String getFilePath() {
        return filePath;
    }

    public void setFilePath(String filePath) {
        this.filePath = filePath;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }
}
upload.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>文件上传</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/upload" method="post" enctype="multipart/form-data">
    文件描述:<input type="text" name="description"><br>
    <input type="file" name="file"><br>
    <br>
    <button type="submit">上传</button>
</form>
</body>
</html>
UploadServlet
package com.mylifes1110.java.controller;

import java.io.*;

import java.sql.SQLException;

import java.util.List;

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 org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import com.mylifes1110.java.bean.Files;
import com.mylifes1110.java.service.FilesService;
import com.mylifes1110.java.service.impl.FilesServiceImpl;

@WebServlet(
    name  = "UploadServlet",
    value = "/upload"
)
public class UploadServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        // 创建磁盘文件项工厂
        DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();

        // 创建核心解析对象
        ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);

        // 解决上传服务器后的文件名称中文乱码问题
        servletFileUpload.setHeaderEncoding("utf-8");

        try {

            // 解析上传请求,获取文件项(包括上传文件和描述文本)
            List<FileItem> fileItems   = servletFileUpload.parseRequest(request);
            String         fileName    = null;
            String         description = null;
            int            path2       = 0;
            int            path3       = 0;

            for (FileItem fileItem : fileItems) {

                // 判断fileItem是否是一个上传文件
                if (fileItem.isFormField()) {

                    // 描述文本(打印描述文本)
                    // 指定描述文本编码为utf-8
                    description = fileItem.getString("utf-8");
                    System.out.println(description);
                } else {

                    // 上传文件
                    // 获取上传文件的输入流(该输入流包含了上传文件的数据)
                    InputStream         inputStream         = fileItem.getInputStream();
                    BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);

                    // 获取服务器真实路径
                    String realPath = request.getServletContext().getRealPath("upload");
                    File   file     = new File(realPath);

                    // 判断该文件夹是否存在,如果不存在就创建此文件夹
                    if (!file.exists()) {
                        file.mkdir();
                    }

                    // 文件名称保证唯一性(文件名称 = 当前时间毫秒值 + 文件名称)
                    fileName = System.currentTimeMillis() + "-" + fileItem.getName();

                    // 获取文件hash码
                    int hashCode = fileName.hashCode();

                    // 使用hash码进行与运算并生成二级目录
                    path2 = hashCode & 15;

                    // 使用hash码进行与运算并生成三级目录
                    path3 = (hashCode >> 4) & 15;

                    // 将一级、二级、三级目录拼接并生成完整目录路径
                    String path    = realPath + File.separator + path2 + File.separator + path3;
                    File   newFile = new File(path);

                    // 创建多级目录
                    if (!newFile.exists()) {
                        newFile.mkdirs();
                    }

                    // 准备读写文件
                    FileOutputStream     fileOutputStream     = new FileOutputStream(path + File.separator + fileName);
                    BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
                    byte[]               bytes                = new byte[8192];
                    int                  len                  = -1;

                    while ((len = bufferedInputStream.read(bytes)) != -1) {
                        bufferedOutputStream.write(bytes, 0, len);
                    }

                    bufferedInputStream.close();
                    bufferedOutputStream.close();
                }
            }

            FilesService filesService = new FilesServiceImpl();
            Files        files        = new Files();

            files.setFileName(fileName);

            // 封装后准备存入数据库(注意:该路径不是盘符服务器目录的真实路径,而是项目资源目录路径)
            files.setFilePath("/fileupload" + File.separator + "upload" + path2 + File.separator + path3
                              + File.separator + fileName);
            files.setDescription(description);
            filesService.addFiles(files);
            response.sendRedirect(request.getContextPath() + "/list");
        } catch (FileUploadException | SQLException e) {
            e.printStackTrace();
        }
    }
}
DownloadServlet
package com.mylifes1110.java.controller;

import java.io.*;

import java.net.URLEncoder;

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 sun.misc.BASE64Encoder;

@WebServlet(
    name  = "DownloadServlet",
    value = "/download"
)
public class DownloadServlet extends HttpServlet {

    /**
     * base64编码
     *
     * @param fileName 文件名称
     * @return 返回一个处理编码后的文件名称
     */
    public String base64EncodeFileName(String fileName) {
        BASE64Encoder base64Encoder = new BASE64Encoder();

        try {
            return "=?UTF‐8?B?" + new String(base64Encoder.encode(fileName.getBytes("utf-8"))) + "?=";
        } catch (Exception e) {
            e.printStackTrace();

            throw new RuntimeException(e);
        }
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String fileName = request.getParameter("filename");

        // 获取下载文件的媒体类型
        String mimeType = request.getServletContext().getMimeType(fileName);

        // 1.设置媒体类型
        response.setContentType(mimeType);

        // 2.设置下载窗口  "Content-Disposition"

        /**
         * 不同的浏览器对文件名称的编码方式不同,以google浏览器为代表的是以utf-8对文件名称进行编码
         * 其他的一些浏览器以base64对文件名称进行编码
         * 判断使用的浏览器的类型User-Agent
         */
        String userAgent   = request.getHeader("User-Agent");
        String newFileName = null;

        if (userAgent.contains("Chrome")) {

            // Google浏览器以utf-8进行编码
            newFileName = URLEncoder.encode(fileName, "utf-8");
        } else {

            // 其他浏览器以base64进行编码
            newFileName = base64EncodeFileName(fileName);
        }

        // Google浏览器:new String(fileName.getBytes("utf-8"), "ISO8859-1")
        response.setHeader("Content-Disposition", "attachement;filename=" + newFileName);

        // 3.IO读写
        String path = request.getServletContext().getRealPath("upload") + File.separator + fileName;

        System.out.println(path);

        BufferedInputStream  bufferedInputStream  = new BufferedInputStream(new FileInputStream(path));
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(response.getOutputStream());
        byte[]               bytes                = new byte[8192];
        int                  len                  = -1;

        while ((len = bufferedInputStream.read(bytes)) != -1) {
            bufferedOutputStream.write(bytes, 0, len);
        }

        bufferedInputStream.close();
        bufferedOutputStream.close();
    }
}
FilesListServlet
package com.mylifes1110.java.controller;

import java.io.IOException;

import java.sql.SQLException;

import java.util.List;

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 com.mylifes1110.java.bean.Files;
import com.mylifes1110.java.service.FilesService;
import com.mylifes1110.java.service.impl.FilesServiceImpl;

@WebServlet(
    name  = "FilesListServlet",
    value = "/list"
)
public class FilesListServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        FilesService filesService = new FilesServiceImpl();

        try {
            List<Files> filesList = filesService.selectFiles();

            request.setAttribute("files", filesList);

            request.getRequestDispatcher("/filesList.jsp").forward(request, response);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
filesList.jsp文件列表展示页面
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
  Created by IntelliJ IDEA.
  User: mylif
  Date: 2020/5/7
  Time: 14:16
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>文件列表</title>
    <style>
        a{
            text-decoration: none;
        }
    </style>
</head>
<body>
<table border="1px" cellpadding="10px" cellspacing="0px">
    <tr>
        <td>编号</td>
        <td>文件名称</td>
        <td>文件描述</td>
        <td>操作</td>
    </tr>
<c:forEach items="${files}" var="file">
<tr>
    <td>${file.id}</td>
    <td><a href="${file.filePath}">${file.fileName}<a/></td>
    <td>${file.description}</td>
    <td><a href="${pageContext.request.contextPath}/download?filename=${file.fileName}">下载</a></td>
</tr>
</c:forEach>
</table>
</body>
</html>
FilesDao
package com.mylifes1110.java.dao;

import com.mylifes1110.java.bean.Files;

import java.sql.SQLException;
import java.util.List;

public interface FilesDao {
    void addFiles(Files files) throws SQLException;

    List<Files> selectFiles() throws SQLException;
}
FilesDaoImpl
package com.mylifes1110.java.dao.impl;

import java.sql.SQLException;

import java.util.List;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import com.mylifes1110.java.bean.Files;
import com.mylifes1110.java.dao.FilesDao;
import com.mylifes1110.java.utils.DBUtils;

public class FilesDaoImpl implements FilesDao {
    @Override
    public void addFiles(Files files) throws SQLException {
        new QueryRunner(DBUtils.getDataSource()).update(
            "insert into tb_uploadfiles (filename, filepath, description) values (?, ?, ?)",
            files.getFileName(),
            files.getFilePath(),
            files.getDescription());
    }

    @Override
    public List<Files> selectFiles() throws SQLException {
        return new QueryRunner(DBUtils.getDataSource()).query("select * from tb_uploadfiles",
                                                              new BeanListHandler<Files>(Files.class));
    }
}
FilesService
package com.mylifes1110.java.service;

import java.sql.SQLException;
import java.util.List;

import com.mylifes1110.java.bean.Files;

public interface FilesService {
    void addFiles(Files files) throws SQLException;

    List<Files> selectFiles() throws SQLException;
}
FilesServiceImpl
package com.mylifes1110.java.service.impl;

import java.sql.SQLException;
import java.util.List;

import com.mylifes1110.java.bean.Files;
import com.mylifes1110.java.dao.FilesDao;
import com.mylifes1110.java.dao.impl.FilesDaoImpl;
import com.mylifes1110.java.service.FilesService;

public class FilesServiceImpl implements FilesService {
    private FilesDao filesDao = new FilesDaoImpl();

    @Override
    public void addFiles(Files files) throws SQLException {
        filesDao.addFiles(files);
    }

    @Override
    public List<Files> selectFiles() throws SQLException {
        return filesDao.selectFiles();
    }
}

四、自定义文件上传

4.1 文件上传分析

  • 【客户端】输入流,从硬盘读取文件数据到程序中
  • 【客户端】输出流,写出文件数据到服务端
  • 【服务端】输入流,读取文件数据到服务端程序
  • 【服务端】输出流,写出文件数据到服务器硬盘中

【文件上传和下载教科书】分分钟掌握JavaWeb中文件上传和下载(学习总结)

4.2 自定义文件上传细节处理

4.2.1 文件名称重复发生覆盖问题

服务器端保存文件的名称如果写死,那么最终导致服务器硬盘,只会保留一个文件(文件发生了覆盖),建议使 用系统时间优化,保证文件名称唯一

String path = "C:\\Users\\mylif\\Desktop\\" + System.currentTimeMillis() + "-java.jpg";
4.2.2 服务器端接收一次后关闭问题

正常的服务器理论来说是不会关闭的,除非你想停止服务。如果想继续服务就不能关闭服务器。但是写的代码,接收客户端的一次请求就关闭了怎么办?我们这时需要加一个while(true),对,没错。就是死循环(无限循环),加一个无限循环来保持服务器一直处在运行状态!

whiletrue{
Socket accept = serverSocket.accept();
//服务器处理的代码
}
4.2.3 多线程问题

大家都知道,服务器是接收用户请求的,但是不只是接收一个用户请求。普通的编写服务器代码在接收大文件时,可能耗费几秒钟的时间,此时不能接收其他用户上传,所以,使用多线程技术优化服务器!

whiletrue{
Socket accept = serverSocket.accept();
// accept 交给子线程处理.
new Thread(()> {
//服务器代码
InputStream bis = accept.getInputStream();
//服务器代码
}).start();

4.3 自定义文件上传代码实现

  • port(端口):自定义端口,不要与其他应用服务器端口发生冲突
  • IP地址:cmdDOS命令窗口执行ipconfig查看自己的ip地址,也可以在项目中写localhost(默认本机ip)

注意:IO流程的关闭必须写在finally块中,以保证服务器不提前关闭和IO流程最终关闭;启动时,先启动服务器,后启动客户端

服务器端代码
package com.mylifes1110.java.upload;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import java.net.ServerSocket;
import java.net.Socket;

/**
 * 文件上传接收端(服务器端)
 */
public class Receiver {
    public static void main(String[] args) {
        try {

            // 获取接收端的套接字
            ServerSocket serverSocket = new ServerSocket(10200);

            while (true) {
                new Thread() {
                    @Override
                    public void run() {
                        BufferedInputStream  bufferedInputStream  = null;
                        BufferedOutputStream bufferedOutputStream = null;

                        try {
                            Socket socket = serverSocket.accept();

                            // 获取对应的输入流,包含了发送端发送过来的数据
                            bufferedInputStream = new BufferedInputStream(socket.getInputStream());

                            String path = "C:\\Users\\mylif\\Desktop\\" + System.currentTimeMillis() + "-java.jpg";

                            bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(path));

                            byte[] bytes = new byte[8192];
                            int    len   = -1;

                            while ((len = bufferedInputStream.read(bytes)) != -1) {
                                bufferedOutputStream.write(bytes, 0, len);
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        } finally {
                            try {
                                if (bufferedInputStream != null) {
                                    bufferedInputStream.close();
                                    bufferedInputStream = null;
                                }

                                if (bufferedOutputStream != null) {
                                    bufferedOutputStream.close();
                                    bufferedOutputStream = null;
                                }
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
客户端代码
package com.mylifes1110.java.upload;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.IOException;

import java.net.InetAddress;
import java.net.Socket;

/**
 * 文件上传发送端(客户端)
 */
public class Sender {
    public static void main(String[] args) {

        // 获取本地文件对应的输入流
        String               path                 = "C:\\Users\\mylif\\Desktop\\素材\\图标\\java.jpg";
        BufferedOutputStream bufferedOutputStream = null;
        BufferedInputStream  bufferedInputStream  = null;

        try {
            bufferedInputStream = new BufferedInputStream(new FileInputStream(path));

            Socket socket = new Socket(InetAddress.getByName("localhost"), 10200);

            bufferedOutputStream = new BufferedOutputStream(socket.getOutputStream());

            byte[] bytes = new byte[8192];
            int    len   = -1;

            while ((len = bufferedInputStream.read(bytes)) != -1) {
                bufferedOutputStream.write(bytes, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (bufferedOutputStream != null) {
                    bufferedOutputStream.close();
                    bufferedOutputStream = null;
                }

                if (bufferedInputStream != null) {
                    bufferedInputStream.close();
                    bufferedInputStream = null;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

持续更新中…
有兴趣的可以添加微信,我们在学习交流群中不见不散!

【文件上传和下载教科书】分分钟掌握JavaWeb中文件上传和下载(学习总结)