JavaWeb中文件上传与下载

2023-11-12

JavaWeb中文件上传与下载

一、文件上传

1.文件上传的应用

比如个人信息的管理,上传头像
比如商品信息的管理,上传商品的图片
这些都需要通过浏览器客户端将图片上传到服务器的磁盘上

文件上传原理
所谓的文件上传就是服务器端通过request对象获取输入流,将浏览器端上传的数据读取出来,保存到服务器端

2.客户端浏览器注意事项

1.请求方式必须是 post
2.需要使用组件
3.表单必须设置enctype=“multipart/form-data”

3.服务器端处理

通过request对象,获取InputStream, 可以将浏览器提交的所有数据读取到.

4.上传开源框架-commons-upload

Apache 开源组织提供了一个用来处理表单文件上传的一个开源组件( Commons-fileupload ),该组件性能优异,并且其API使用极其简单,可以让开发人员轻松实现web文件上传功能,因此在web开发中实现文件上传功能,通常使用Commons-fileupload组件实现。

使用Commons-fileupload组件实现文件上传,需要导入该组件相应的支撑jar包:Commons-fileupload和commons-io,
commons-io 不属于文件上传组件的开发jar文件,但Commons-fileupload 组件从1.1 版本开始,它工作时需要commons-io包的支持

5.文件上传案例

在浏览器端创建一个可以上传文件的表单,在服务器端通过commons-fileupload完成文件上传。
浏览器端注意三件事情:
1.表单的method=post
2.设置enctype=multipart/form-date
3.使用具有name属性的file元素
在服务器端
1.创建DiskFileItemFactory
2.创建ServletFileUpload
3.通过ServletFileUpload的parseRequest方法得到所有的FileItem

1.设置浏览器端

<form action="Upload" method="post" enctype="multipart/form-data">
		<input type="file" name="photo"/>
		<input type="submit" value="上传"/>
</form> 

2.在服务器端操作

关键类:
DiskFileItemFactory:ServletFileUpload工厂类
ServletFileUpload:用于处理文件上传的类
IOUtils:文件上传IO流类
BeanUtils:存储表单内文本信息类

//设置乱码
upload.setHeaderEncoding(“UTF-8”);

//ServletFileUpload工厂类
DiskFileItemFactory factory = new DiskFileItemFactory();
//处理文件上传的类
ServletFileUpload upload = new ServletFileUpload(factory);
try {
//获得表带内容
	List<FileItem> items = upload.parseRequest(request);
		for(FileItem fileItem : items) {
			if(!fileItem.isFormField()){//判断非文本信息
			FileOutputStream fos = new 							  									FileOutputStream("C:\\test.jpg");
			IOUtils.copy(fileItem.getInputStream(),fos);//拷贝
			fos.close();
			}
		}
} catch (FileUploadException e) {
e.printStackTrace();
}

完善细节
1.设置保存上传文件的服务器目录

DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
try {
	List<FileItem> items = upload.parseRequest(request);
	for(FileItem fileItem : items) {
		if(!fileItem.isFormField()){
			//获取项目在当前系统下的路径+"upload"
			String path = this.getServletContext().getRealPath("Nupload");
			File dir = new File(path);
			if(!dir.exists())){/判断文件夹是否存在
			dir.mkdirs();
		}
		String filename = fileItem.getName();//获得当前上传文件的名字
		FileOutputStream fos = new FileOutputStream(new File(dir,filename));
		IOUtils.copy(fileItem.getInputStream(),fos);fos.close();1
} catch (FileUploadException e) {
	e.printStackTrace();
}

2.解决上传文件名是中文的问题,通过item.getName()获取到文件的名称

a)直接将其改名,不用原来的名字
b)保存其中文的名字(注意,一般如果是压缩文件供下载的资源,则可以考虑保留其中文名称,否则一般图片直接展示用的,不建议用中文名来保存)

思考题:文件名重复了怎么办?
问题:覆盖
解决方案:
客户端参与
方案一:做个文件名的唯一性校验,告诉客户端,这个文件名已经存在(不建议)
服务端解决
方案二:重新取个名字(唯一性:时间、UUID)—图片资源
利用时间保证唯一性:System.currentTimeMillis()

6.利用UUID保证唯一性

DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
try {
	List<FileItem> items = upload.parseRequest(request);
	for(FileItem fileItem : items) {
		if(!fileItem.isFormField())[
			//获取项目在当前系统下的路径+"upload"
			String path = this.getServletContext().getRealPath("\\upload");
			File dir = new File(path);
			if(!dir.exists()){//判断文件夹是否存在
			dir.mkdirs();
			}
		UUID randomUUID = UUID.randomUUID();
		String filename = randomUUID + "_" + fileItem.getName();//获得当前上传文件的名字			FileOutputStream fos = new FileOutputStream(new File(dir,filename));
		IOUtils.copy(fileItem.getInputStream(),fos);
		fos.close();
	}

2,方案三:下载电影压缩包,水野朝阳.zip 保留原有的名字

for(FileItem fileItem : items) {
	if(!fileItem.isFormField()){
	//获取项目在当前系统下的路径+"upload"
	String path = this.getServletContext().getRealPath("\\upload");
	File dir = new File(path);
	if(!dir.exists()){//判断文件夹是否存在
	dir.mkdirs();
}
	//在原来路径的基础上添加时间路径,做到图片不覆盖的效果
	Date date = new Date();
	SimpleDateFormat sdf = new SimpleDateFormat("yyyy/M/dd/hhmmss");
	String datePath = sdf.format(date);File uploadDir = new File(dir,datePath);
	if(!uploadDir.exists())[
		uploadDir.mkdirs();
	}
	String filename = fileItem.getName());//获得当前上传文件的名字
	FileOutputStream fos = new FileOutputStream(new File(uploadDir,filename));
	IOUtils.copy(fileItem.getInputStream(),fos);fos.close();
}

7.获取完整的表单数据

保存一个完整的表单信息,除了将文件上传到服务器以外,还需要将其他表单项信息保存到对象,并存储到数据中心,而对应的图片信息则保存为保存的路径即可。
那么怎么获取到其他的表单项数据?item.getFileName(),item.getString()
为了更好完成对其他表单项的值的获取,需要借助另一个开源框架 BeanUtils
它除了自身的jar包,还依赖于commons-logging.jar

//创建一个Map来存储普通的表单项数据
Map<String,String>map = new HashMap<>();
//创建一个对象来存储各项数据
Book book = new Book();
	for(FileItem item : list){
		if(item.isFormField()){
		//普通表单项
		//System.out.println(item.getFieldName()+":"+item.getString("utf-8"));//实现一个通用的方法来将对应的参数都赋值到对象上
		map.put(item.getFieldName(),item.getString("utf-8"));
		}else{
			//上传文件//创建上传的目录
			File dir = new File(this.getServletContext().getRealPath("/upload"));
			if(!dir.exists()){
			dir.mkdirs();
			}
			//设置文件名的唯一性
			String fileName = item.getName();
			fileName = FilenameUtils.getName(fileName);
			fileName = UUID.randomUUID()+"_"+fileName;//上传文件
		FileOutputStream outputStream = new FileOutputStream(new File(dir, fileName));
		IOUtils.copy(item.getInputStream(),outputStream);
		book.setImgUrl("upload"+File.separator+fileName);
		outputStream.close();
		}
		item.delete();
	}
		BeanUtils.populate(book,map);
}		

细节:
有复选框的情况怎么办?

String name = fileItem.getFieldName();
String value = fileItem.getString("UTF-8");
	if(map.get(name) == null){
		map. put(name, value);
		}else{
			map.put(name, map.get(name)+"," + value);
}

8.多文件上传案例

实现多文件的批量上传

<form action="MultiUpload" method=''post" enctype="multipart/form-data">
	<input type="file" name="photo"/>
	<input type="file" name="photo"/>
	<input type="submit" value="上传"/>
</form>

Ps:展示图片-“upload” + File.separator + datePath + File.separator + filename);

二、文件下载

主要实现方式有两种
1.超链接下载
2.以超练级的方式下载压缩文件
3.以超链接的方式下载图片文件
4.以超链接的方式下载中文文件名的文件
5.Servlet下载

有些超链接搞不定的事情就交给Servlet来搞定

<a href="download\photo.zip">下载photo.zip</a>
<a href="download\pipixia.jpg">下载pipixia.jpg</a>
<a href="DownloadServlet">下载头像.zip</a>

采用流的方式来读和写

设置响应的头部信息(告诉客户端是以附件的形式下载)
response.setHeader(“Content-disposition”, “attachment;fileName=”+fileName);
细节:
下载的文件名是中文怎么办?

String realPath = this.getServletContext().getRealPath("download\\头像.zip");
String fileName = realPath.substring(realPath.lastIndexof(")+1);
fileName = URLEncoder.encode(fileName,"UTF-8");
response.setHeader("Content-disposition","attachment;fileName="+fileName);
FileInputStream fis = new FileInputStream(realPath);
ServletOutputStream outputStream = response.getOutputStream();
byte[] b = new byte[1024];
int len = 0
while((len = fis.read(b)) != -1){
	outputStream.write(b,0,len);
}
fis.close();
outputStream.close();
}

三、上传与下载

1.上传

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.IOException;

@WebServlet(urlPatterns = "/upload")
@MultipartConfig(fileSizeThreshold = 1024*100,maxFileSize = 1024*1024*5,maxRequestSize = 1024*1024*25)
public class UploadServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String bookName=   request.getParameter("bookName");
        System.out.println("bookName:"+bookName);
        Part part= request.getPart("bookPic");
        String filename= part.getSubmittedFileName();
        String path="/WEB-INF/upload/"+filename;
        // 把逻辑路径转成物理路径
        // 绝对路径 相对路径不一样的
        path=request.getServletContext().getRealPath(path);
        System.out.println(path);
        part.write(path);
        response.getWriter().print(filename+"上传成功");

    }
}


2.下载

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.*;

@WebServlet(urlPatterns = "/download")
public class DownloadServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      String filename="ggc.docx";
        String path="/WEB-INF/upload/"+filename;
        path=request.getServletContext().getRealPath(path);
        File file=new File(path);
        //准备好了输入流
        InputStream inputStream=new FileInputStream(file);
        response.setHeader("Content-Disposition", "attachment;filename="+filename);
        //浏览器端的输出流
       OutputStream outputStream= response.getOutputStream();
       byte[] datas=new byte[1024];
       int len=0;
       while( (len =inputStream.read(datas))>0){
           outputStream.write(datas,0,len);
       }
       outputStream.close();
       inputStream.close();

    }
}

3.前端

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>文件上传</title>
</head>
<body>
<form name="frmupload" action="/upload" method="post" enctype="multipart/form-data">
    书名:<input name="bookName" type="text"/><br/>
   附件: <input name="bookPic" type="file"/><br/>
    <input name="btnAdd" type="submit" value="保存"/>
</form>
</body>
</html>

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JavaWeb中文件上传与下载 的相关文章

随机推荐

  • macOS通过钥匙串访问找回WiFi密码的详细教程

    如果您忘记了Mac电脑上的WiFi密码 可以通过钥匙串访问来找回它 具体步骤如下 1 打开Mac电脑的 启动台 然后在其他文件中找到 钥匙串访问 2 运行 钥匙串访问 应用程序 点击左侧的 系统 然后在右侧找到要查看的WiFi网络名称 如果
  • 在linux上安装与卸载MySQL【非常详细】

    文章目录 一 安装MySQL 1 从网上下载文件的wget命令 2 下载MySQL的repo源 3 安装MySQL的rpm包 4 检查是否有两个repo源 5 安装MySQL 6 启动MySQL 7 登录MySQL 8 登录并切换数据库 查
  • Leetcode 题组 28

    112 路径总和 给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 判断该树中是否存在 根节点到叶子节点 的路径 这条路径上所有节点值相加等于目标和 targetSum 叶子节点 是指没有子节点的节点 示例 1 输入
  • java 在阻塞时终结学习笔记

    一个线程可以处于以下四种状态 1 新建 new 当线程被创建时 它只会短暂地处于这种状态 此时它已经分配了必需的系统资源 并执行了初始化 此时刻线程已经有资格获得CPU时间了 之后调度器将把这个线程转变为可运行状态或阻塞状态 2 就绪 Ru
  • Python机器学习(三)--决策树算法

    Python机器学习 三 决策树算法 原创 2014年07月14日 13 57 55
  • C语言中的fprintf和printf区别在哪?

    原型 fprintf的函数原型为 int fprintf FILE stream const char format argument 而printf的函数原型为 int printf const char format argument
  • uniapp使用绝对定位被父元素截断问题

    在做uniapp开发时真机运行的时候使用绝对定位 会被他限制在他整个的父元素之内 本来这两块是做了两个子组件 但是 点击问号的时候就会出现上述问题 弹框永远显示不全 解决方案 将这个弹框移到父组件中 如index vue 然后使用一个div
  • jdk下载百度云(windows×64-7,8,10)

    之前找了很久 好多都要很多积分 所以我就给大家整理到百度云盘 https pan baidu com s 1UgiZf6R8PNtnlTDNW N2Kw 提取码 o6cp
  • 只有持续的变革和创新才是CRM成功的关键

    这两年来 我目睹了众多的企业在进行CRM的尝试和体验 也亲历了众多的企业对CRM成功与失败的讨论 甚至于有很多关于CRM失败的项目和言论 让更多后面的企业停止了尝试的脚步 而这一切 不应该只归罪与一个CRM系统 或者一个CRM项目 而要更多
  • error: CreateProcess: No such file or directory的解决方法

    办公的笔记本上先装有qnxIDE的700环境 然后再用Eclipse 搭建了一个qnx710的环境 刚搭建完qnx710的时候是可以编译通过的 之后第二天再开机编译Eclipse 710就编译不过了 报错就是 error CreatePro
  • WiFi技术概述

    1 概述 WLAN是无线局域网络的简称 全称为Wireless Local Area Networks 是一种利用无线技术进行数据传输的系统 该技术的出现能够弥补有线局域网络之不足 以达到网络延伸之目的 Wi Fi是无线保真的缩写 英文全称
  • spring加载一个或者多个properties配置文件方法

    在项目中有些参数需要经常修改 或者后期需要修改 比如IP 调用别人的接口地址 数据库地址及帐号密码等 那么我们就不能把这些参数写死在代码里 虽然也可以在代码里改 但是如果是不懂代码的运维人员去现场部署项目又怎么改你的代码 那我们最好把这些参
  • 关于Discuz X3.2如何设置邮箱验证的具体方法

    原文地址 兔子酱老师好久没发文章了的 是因为最近在学习和熟悉Discuz社区程序 这个PHP程序是一木主编推荐给我的 妹子我简单操作了几下 很是喜欢 这个程序目前的版本是X3 2 带有很多好玩的功能 听说这个程序早几年被腾讯收购了的 所以
  • 控制疫情蔓延嵌入式物联网能帮大忙

    联合国所订定之永续发展目标之一 便是针对防治传染病的蔓延做好准备 在新型冠状病毒 COVID 19 流行期间 防疫已成为当前最重要目标 科技在对抗传染病方面扮演重要角色 而物联网 IoT 相关技术正是我们重要的防疫武器 降低成本 自发自主性
  • matlab 求单/多元函数极值

    matlab 求单 多元函数极值 单元函数极值 平时如果手算的话 就会先求导数 再求驻点 最终代值算出极值 如果用matlab代码求的话 就可以减少很多不必要的计算 fun inline 0 5 x exp x 2 ezplot fun 0
  • java复习第7天---7.4---IO流---递归、文件过滤器

    java复习第7天 7 4 IO流 递归 文件过滤器 目录 文章目录 1 递归 1 1 递归概述和分类 2 过滤器 后记 内容 1 递归 1 1 递归概述和分类 递归 在方法内调用自己 递归分类 递归分为直接递归和间接递归 直接递归 方法内
  • python的gzip库解压某一路径下的所有.gz文件

    今天 做机器学习 解压数据集的时候 参考大佬咯咯哒鸭的文章想到的方法 代码如下 encoding utf 8 Author Mr Pan 学狂 finish time 2022 2 15 import sys import gzip imp
  • 入门级题解5. 最长回文子串

    题目 给你一个字符串 s 找到 s 中最长的回文子串 思路 找到最小的那个字串 aba或者aa 然后向两边发散 伪代码 for 1 s length 第一种情况 if s i s i 1 aa bb cc形式 第二种情况 if s i 1
  • layui跨域问题

    由于浏览器存在同源策略 所以如果 layui 里面含图标字体文件 所在的地址与你当前的页面地址不在同一个域下 即会出现图标跨域问题 所以要么你就把 layui 与网站放在同一服务器 要么就对 layui 所在的资源服务器的 Response
  • JavaWeb中文件上传与下载

    JavaWeb中文件上传与下载 一 文件上传 1 文件上传的应用 比如个人信息的管理 上传头像 比如商品信息的管理 上传商品的图片 这些都需要通过浏览器客户端将图片上传到服务器的磁盘上 文件上传原理 所谓的文件上传就是服务器端通过reque