Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >java 如何实现大文件上传下载(传输)各种格式「建议收藏」

java 如何实现大文件上传下载(传输)各种格式「建议收藏」

作者头像
全栈程序员站长
发布于 2022-09-06 08:45:20
发布于 2022-09-06 08:45:20
3.1K0
举报

大家好,又见面了,我是你们的朋友全栈君。

我们平时经常做的是上传文件,上传文件夹与上传文件类似,但也有一些不同之处,这次做了上传文件夹就记录下以备后用。

这次项目的需求:

支持大文件的上传和续传,要求续传支持所有浏览器,包括ie6,ie7,ie8,ie9,Chrome,Firefox,360安全浏览器,并且刷新浏览器后仍然能够续传,重启浏览器(关闭浏览器后再打开)仍然能够继续上传,重启电脑后仍然能够上传

支持文件夹的上传,要求服务端能够保留层级结构,并且能够续传。需要支持10万个以上的文件夹上传。

支持低版本的系统和浏览器,因为这个项目的最终运行环境在政府,政府的配置都一般,职员都是办公用,内存都不大,基本上以Windows XP的系统为主。

1、介绍enctype

enctype 属性规定发送到服务器之前应该如何对表单数据进行编码。

enctype作用是告知服务器请求正文的MIME类型(请求消息头content-type的作用一样)

1、1 enctype的取值有三种

描述

application/x-www-form-urlencoded

在发送前编码所有字符(默认)

multipart/form-data

不对字符编码。每一个表单项分割为一个部件

text/plain

空格转换为 “+” 加号,但不对特殊字符编码。

1. 当enctype=’application/x-www-form-urlencoded’

2.当enctype=’multipart/form-data’

通过观察发现这个的请求体就发生了变化。这种请求体被称之为多部件请求体。

什么是多部件请求体:就是把每一个表单项分割为一个部件。

以请求头的content-type的boundary后面的一串随机字符串作为分割标识

普通表单项:

//name的意思是文本框里面name的属性值,而admin是我们输入的文本值

Content-Disposition: form-data; name=”username”

admin

文件表单项

//filename的意思是:我们上传的文件名称,content-Type的意思是:MIME类型,asdasdas的意思是:文件里面的内容

Content-Disposition: form-data; name=”upload”; filename=”a.txt”

Content-Type: text/plain

asdasdas

3. 当enctype=’text/plain’

w3c称:空格会变成”+”加号,但是我这里没有发现,只有当get请求的时候,空格会变成”+”号

进入正题

完成上传需要满足3个必要的条件

提供form表单,method必须是post,因为get请求的传输数据一般为2kb,不同浏览器不一样。

form表单属性enctype的必须是multipart/form-data

提供input type=”file”类的上传输入域

大致实现原理:当enctype的值是multipart/form-data时,浏览器会把每个表单项进行分割,分割成不同的部件,以boundary的值为分割标识,这个标识的字符串是随机生成的,最后一个表单项的分割标识字符串末尾会多两个”- -“,代表结束。服务端用request.getHeader(“content-type”)获取分割字符串,然后进行解析。

代码实现

一、开发环境搭建

准备两个第三方jar包

commons-io包

commons-upload包

所有依赖包

代码实现

<%@ page language=”java” import=”up6.DBFile” pageEncoding=”UTF-8″%>

<%@ page contentType=”text/html;charset=UTF-8″%>

<%@ page import=”up6.FileBlockWriter” %>

<%@ page import=”up6.XDebug” %>

<%@ page import=”up6.*” %>

<%@ page import=”up6.biz.*” %>

<%@ page import=”org.apache.commons.fileupload.FileItem” %>

<%@ page import=”org.apache.commons.fileupload.FileItemFactory” %>

<%@ page import=”org.apache.commons.fileupload.FileUploadException” %>

<%@ page import=”org.apache.commons.fileupload.disk.DiskFileItemFactory” %>

<%@ page import=”org.apache.commons.fileupload.servlet.ServletFileUpload” %>

<%@ page import=”org.apache.commons.lang.*” %>

<%@ page import=”java.net.URLDecoder”%>

<%@ page import=”java.util.Iterator”%>

<%@ page import=”net.sf.json.JSONObject”%>

<%@ page import=”java.util.List”%>

<%

out.clear();

String uid = request.getHeader(“uid”);//

String id = request.getHeader(“id”);

String lenSvr = request.getHeader(“lenSvr”);

String lenLoc = request.getHeader(“lenLoc”);

String blockOffset = request.getHeader(“blockOffset”);

String blockSize = request.getHeader(“blockSize”);

String blockIndex = request.getHeader(“blockIndex”);

String blockMd5 = request.getHeader(“blockMd5”);

String complete = request.getHeader(“complete”);

String pathSvr = “”;

//参数为空

if( StringUtils.isBlank( uid )

|| StringUtils.isBlank( id )

|| StringUtils.isBlank( blockOffset ))

{

XDebug.Output(“param is null”);return;

}

boolean isMultipart = ServletFileUpload.isMultipartContent(request);

FileItemFactory factory = new DiskFileItemFactory();

ServletFileUpload upload = new ServletFileUpload(factory);

List files = null;

try {files = upload.parseRequest(request);}

catch (FileUploadException e)

{out.println(“read file data error:” + e.toString());return;}

FileItem rangeFile = null;

Iterator fileItr = files.iterator();

while (fileItr.hasNext())

{

rangeFile = (FileItem) fileItr.next();

if(StringUtils.equals( rangeFile.getFieldName(),”pathSvr”))

{

pathSvr = rangeFile.getString();

pathSvr = PathTool.url_decode(pathSvr);

}

}

boolean verify = false;

String msg = “”;

String md5Svr = “”;

long blockSizeSvr = rangeFile.getSize();

if(!StringUtils.isBlank(blockMd5)){md5Svr = Md5Tool.fileToMD5(rangeFile.getInputStream());}

verify = Integer.parseInt(blockSize) == blockSizeSvr;

if(!verify){ msg = “block size error sizeSvr:” + blockSizeSvr + “sizeLoc:” + blockSize;}

if(verify && !StringUtils.isBlank(blockMd5))

{

verify = md5Svr.equals(blockMd5); if(!verify) msg = “block md5 error”;

}

if(verify)

{

FileBlockWriter res = new FileBlockWriter();

if( Integer.parseInt(blockIndex)==1) res.CreateFile(pathSvr,Long.parseLong(lenLoc));

res.write( Long.parseLong(blockOffset),pathSvr,rangeFile);

up6_biz_event.file_post_block(id,Integer.parseInt(blockIndex));

JSONObject o = new JSONObject();

o.put(“msg”, “ok”);

o.put(“md5”, md5Svr);

o.put(“offset”, blockOffset);

msg = o.toString();

}

rangeFile.delete();

out.write(msg);

%>

下载的必须条件

两个头一个流

content-type

Content-Type是返回消息中非常重要的内容,表示文档内容属于什么MIME类型。

浏览器会根据Content-Type来决定如何显示返回的消息体内容。

默认值是text/html

可以使用request.getServletContext().getMimeType(“文件名”)获取MIME类型。

Content-Disposition

Content-disposition 是 MIME 协议的扩展,MIME 协议指示 MIME 用户代理如何显示附加的文件。

默认值是inline,表示在浏览器窗口中打开。

服务端向客户端游览器发送文件时,如果是浏览器支持的文件类型,一般会默认使用浏览器打开,比如txt、jpg等,会直接在浏览器 中显示。

如果需要提示用户保存,利用Content-Disposition进行一下处理,关键在于一定要加上attachment。

例如:Content-Disposition:attachment;filename=xxx,浏览器就会激活下载框对话框, attachment 表示附件, filname 后面跟随的是显示在下载框中的文件名称。

下载就是向客户端响应字节数据! 将一个文件变成字节数组, 使用 response.getOutputStream()

来响应给浏览器。

代码如下,此代码已经实现了断点续传功能,用户在下载过程可以暂停,和继续下载,对服务器造成的压力也比较小。

String fid = request.getHeader(“id”);

String blockIndex = request.getHeader(“blockIndex”);//基于1

String blockOffset = request.getHeader(“blockOffset”);//块偏移,相对于整个文件

String blockSize = request.getHeader(“blockSize”);//块大小(当前需要下载的大小)

String pathSvr = request.getHeader(“pathSvr”);//文件在服务器的位置

pathSvr = PathTool.url_decode(pathSvr);

if ( StringUtils.isBlank(fid)

||StringUtils.isBlank(blockIndex)

||StringUtils.isEmpty(blockOffset)

||StringUtils.isBlank(blockSize)

||StringUtils.isBlank(pathSvr))

{

response.setStatus(500);

response.setHeader(“err”,”参数为空”);

return;

}

File f = new File(pathSvr);

//文件不存在

if(!f.exists())

{

response.setStatus(500);

OutputStream os = response.getOutputStream();

System.out.println(String.format(“%s 文件不存在”,pathSvr));

os.close();

return;

}

long fileLen = f.length();

response.setContentType(“application/x-download”);

response.setHeader(“Pragma”,”No-cache”);

response.setHeader(“Cache-Control”,”no-cache”);

response.addHeader(“Content-Length”,blockSize);

response.setDateHeader(“Expires”, 0);

OutputStream os = response.getOutputStream();

try

{

RandomAccessFile raf = new RandomAccessFile(pathSvr,”r”);

int readToLen = Integer.parseInt(blockSize);

int readLen = 0;

raf.seek( Long.parseLong(blockOffset) );//定位索引

byte[] data = new byte[1048576];

while( readToLen > 0 )

{

readLen = raf.read(data,0,Math.min(1048576,readToLen) );

readToLen -= readLen;

os.write(data, 0, readLen);

}

os.flush();

os.close();

raf.close();

os = null;

response.flushBuffer();

out.clear();

out = pageContext.pushBody();

}

catch(Exception e)

{

response.setStatus(500);

os.close();

out.close();

e.printStackTrace();

}

finally

{

if(os != null)

{

os.close();

os = null;

}

out.clear();

out = pageContext.pushBody();

}%>

加载文件列表,在下载列表中显示出来

后端代码逻辑大部分是相同的,目前能够支持MySQL,Oracle,SQL。在使用前需要配置一下数据库,可以参考我写的这篇文章:java http大文件断点续传上传 – 泽优软件博客

欢迎入群一起讨论“374992201”

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/154893.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Flask 实现文件上传下载
Flask 针对文件的上传下载相关代码片段,多种方法,包括限制文件格式,大小等。 实现图片文件上传 # name: 简单的实现文件上传任务. import os from flask import Flask, request, url_for, send_from_directory from werkzeug import secure_filename ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg', 'gif']) app = Flask(__nam
王 瑞
2022/12/28
1.1K0
Java文件上传下载实训
文件上传概述 1 文件上传的作用 例如网络硬盘!就是用来上传下载文件的。 在智联招聘上填写一个完整的简历还需要上传照片呢。 2 文件上传对页面的要求 上传文件的要求比较多,需要记一下: 1. 必须使用表单,而不能是超链接; 2. 表单的method必须是POST,而不能是GET; 3. 表单的enctype必须是multipart/form-data; 4. 在表单中添加file表单字段,即<input type=”file”…/> <form action="${pageContext.request.c
Java帮帮
2018/03/19
1.8K1
Java文件上传下载实训
Springboot大文件上传下载实现思路,分片、断点续传代码
WebUploader是由Baidu WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件。
星辰大海的精灵
2024/12/03
5941
SpringMVC-07 拦截器+文件上传下载
SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。开发者可以自己定义一些拦截器来实现特定的功能。
张小驰出没
2021/04/15
5810
SpringMVC-07  拦截器+文件上传下载
GridFs文件上传下载
文章目录[隐藏] 业务层 上传 下载 预览 配置文件 业务层 public class FileMonService { /** * 操作GridFs接口 */ private final GridFsTemplate gridFsTemplate; @Autowired public FileMonService(GridFsTemplate gridFsTemplate) { this.gridFsTemplate = grid
用户10325771
2023/03/01
5740
Servlet 3.0 文件上传与下载
主要是用到了客户端 HTML 页面的表单元素,使用<form> 标签的 enctype 属性,并设置它的值为 multipart/formdata,意思是:多部分/表单数据,同时使用<input type="file"> 的输入域用于指定上传的文件。
wsuo
2020/07/30
1.1K0
Servlet 3.0 文件上传与下载
一文读懂SpringMVC中的文件上传与下载
这两天研究了一下 SpringMVC 中文件上传与下载,也遇到了一些坑,这里做个总结。
Wizey
2018/09/29
1.7K4
一文读懂SpringMVC中的文件上传与下载
maven 项目 springMVC实现文件图片的上传下载功能详解(源码已提供,小白必看)
文件上传是项目开发中最常见的功能之一 ,springMVC 可以很好的支持文件上传,但是SpringMVC上下文中默认没有装配MultipartResolver,因此默认情况下其不能处理文件上传工作。如果想使用Spring的文件上传功能,则需要在上下文中配置MultipartResolver。
一写代码就开心
2020/11/19
2.1K1
maven 项目  springMVC实现文件图片的上传下载功能详解(源码已提供,小白必看)
基于Spring Mvc实现的Excel文件上传下载
最近工作遇到一个需求,需要下载excel模板,编辑后上传解析存储到数据库。因此为了更好的理解公司框架,我就自己先用spring mvc实现了一个样例。 基础框架 之前曾经介绍过一个最简单的spring mvc的项目如何搭建,传送门在这里。 这次就基于这个工程,继续实现上传下载的小例子。需要做下面的事情: 1 增加index.html,添加form提交文件 2 引入commons-fileupload、commons-io、jxl等工具包 3 创建upload download接口 4 注入multip
用户1154259
2018/01/17
1.6K0
深入理解文件上传下载的原理及实现逻辑
文件上传的是根据 http 协议的规范和定义,完成请求消息体的封装和消息体的解析,然后将二进制内容保存到文件。
Lion 莱恩呀
2025/01/01
4360
深入理解文件上传下载的原理及实现逻辑
springboot (八) 文件上传下载
springboot项目中实现简单的上传和下载。 新建springboot项目,前台页面使用的thymeleaf模板,其余的没有特别的配置,pom代码如下: <?xml version="1.0" e
IT架构圈
2018/06/01
1.3K0
JavaWeb20-文件上传;下载(Java真正的全栈开发)
文件上传&下载一.文件上传 1. 文件上传介绍 要将客户端(浏览器)大数据存储到服务器端,不将数据直接存储到数据库中,而是要将数据存储到服务器所在的磁盘上,这就要使用文件上传。 作用:减少了数据库服务器的压力,对数据的操作更加灵活 2. 文件上传原理分析 所谓的文件上传就是服务器端通过request对象获取输入流,将浏览器端上传的数据读取出来,保存到服务器端 浏览器端操作 1.请求方式必须是post 2.使用<input type=’file’ name=’xxx’>,必须有name属性且有值 3.表单
Java帮帮
2018/03/19
1K0
JavaWeb20-文件上传;下载(Java真正的全栈开发)
Django之文件上传下载
在文件上传期间,实际文件数据存储在request.FILES中。此字典中的每个条目都是UploadedFile对象(或子类) – 上传文件的简单包装器。UploadedFile对象是对Python file对象的一个简单封装,并带有Django特定的附加功能。需要表示文件的时候,Django内部会使用这个类。UploadedFile对象拥有下列属性和方法:
菲宇
2022/05/06
3.7K0
SpringMVC文件上传下载
文件上传和下载是互联网web应用非常重要的组成部分,它是信息交互传输的重要渠道之一。你可能经常在网页上传下载文件,你可能也曾沉浸于互联网技术的神秘,而本篇就为你解开它神秘的面纱。
bigsai
2020/08/04
7870
SpringMVC文件上传下载
SpringMVC上传下载
1、需要导入jar包:ant.jar、commons-fileupload.jar、connom-io.jar。当然spring jar包不可缺少的哦  我这里用的是spring+springmvc+hibernate  可以到官网上直接下载springmvcjar即可
用户7705674
2021/09/23
4970
文件的上传和下载
文件的上传和下载,是非常常见的功能,在很多的系统中,或者软件中都经常使用文件的上传和下载。 比如:QQ头像,就使用了上传 邮箱中也有附件的上传和下载的功能
技术交流
2022/11/18
1.4K0
文件的上传和下载
SpringBoot文件上传下载
项目中经常会有上传和下载的需求,这篇文章简述一下springboot项目中实现简单的上传和下载。 新建springboot项目,前台页面使用的thymeleaf模板,其余的没有特别的配置,pom代码如
dalaoyang
2018/04/28
1.1K0
javaEE项目Multipartfile实现文件上传下载并解决上传与下载文件中文乱码的问题
里面包含了文件上传下载并解决上传与下载文件中文乱码的问题,运用正则表达式判断字符串中是否包含中文和得到一个文件夹下的所有文件的方法,几乎集合了上传下载所需要的所有东西.下面代码加红的部分就是这几个重要点!
洋仔聊编程
2019/01/15
2.4K0
java web文件上传——FileUpload
1.普通表单提交默认enctype=”application/x-www-form-urlencoded”;但是当表单中存在文件类型时,需要设置enctype=”multipart/form-data”,它不对字符进行编码,用于发送二进制的文件(即所有文件类型,如视频、图片、音乐、文档都可以用此类型entype);还有一种enctype=”text/plain”用于发送纯文本内容。
全栈程序员站长
2022/08/28
1.8K0
java web文件上传——FileUpload
Web阶段:第十五章:文件上传&amp;下载
文件的上传 1、首先需要一个form表单 2、然后在表单内有input type=”file” 3、提交的方式必须是method=”POST” 4、enctype="multipart/form-data"编码类型必须是多段的表单数据
Java廖志伟
2022/09/28
3720
Web阶段:第十五章:文件上传&amp;下载
相关推荐
Flask 实现文件上传下载
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档