You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
text/web/message.jsp

103 lines
8.0 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!-- JSP 页面指令,设置页面内容类型为 HTML字符编码为 UTF-8表明该页面使用 Java 语言编写 -->
<%@ page import="java.io.*,java.util.*,javax.servlet.*,javax.servlet.http.*" %>
<!-- 导入多个 Java 相关的包用于处理输入输出、集合操作、Servlet 相关功能以及 HTTP 相关功能等,方便后续代码中使用这些类和接口 -->
<%@ page import="java.rmi.ServerException" %>
<!-- 导入用于处理服务器端异常的类,可能用于在出现问题时抛出合适的异常信息 -->
<%@ page import="java.nio.charset.Charset" %>
<%@ page import="java.nio.charset.StandardCharsets" %>
<!-- 导入字符编码相关的类和标准字符编码常量,用于处理字符编码转换等操作,比如后续将字节数组转换为字符串时指定编码 -->
<html>
<head>
<title></title>
</head>
<body>
<%
//定义上传文件的最大字节数,这里设置的数值是 102400 * 102400 字节(不过这个数值看起来可能过大,也许是示例或特殊需求,通常会根据实际情况合理设置大小限制)
int MAX_SIZE = 102400 * 102400;
//创建根路径的保存变量,后续用于拼接出文件上传后的保存路径,初始时只是声明,还未赋值具体内容
String rootPath;
//声明文件读入类,用于从请求流中读取上传的数据,初始化为 null后续会在合适的逻辑中进行实例化
DataInputStream in = null;
//声明文件输出流类,用于将上传的数据写入到服务器端的文件中,初始化为 null后续会在合适的逻辑中进行实例化
FileOutputStream fileOut = null;
//取得互联网程序(即当前 Servlet 上下文对应的应用程序)的绝对地址,例如获取到类似项目部署在服务器上的根目录路径
String realPath = request.getSession().getServletContext().getRealPath("/");
//对获取到的绝对路径进行处理,截取掉其中 "\out" 及之后的部分,可能是为了获取到项目更合适的基础路径(具体取决于项目结构和需求)
realPath = realPath.substring(0, realPath.indexOf("\\out"));
// out.print(realPath);
// 创建文件的保存目录,将处理后的路径与 "\web\upload\" 拼接起来,形成文件最终要保存的目录路径,这里假设项目中有这样一个用于存放上传文件的目录结构
rootPath = realPath + "\\web\\upload\\";
//取得客户端上传的数据类型,例如判断是否是 "multipart/form-data" 这种常见的文件上传类型的数据格式
String contentType = request.getContentType();
try {
// 判断客户端上传的数据类型是否是 "multipart/form-data",如果是则进行文件上传相关的处理逻辑
if (contentType.indexOf("multipart/form-data") >= 0) {
// 读入上传数据,通过从请求输入流创建 DataInputStream 对象,以便按字节读取客户端上传的数据
in = new DataInputStream(request.getInputStream());
// 获取上传数据的总长度(字节数),用于后续循环读取数据以及判断是否超过设定的最大字节限制
int formDataLength = request.getContentLength();
// 检查上传的数据长度是否超过了预先定义的最大字节数,如果超过则输出提示信息并终止当前方法执行(直接返回)
if (formDataLength > MAX_SIZE) {
out.print("上传的字节不可以超过" + MAX_SIZE + "字节");
return;
}
// 保存上传文件的数据,创建一个字节数组,大小为上传数据的总长度,用于存放从请求中读取到的字节数据
byte dataBytes[] = new byte[formDataLength];
int byteRead = 0;
int totalBytesRead = 0;
// 上传的数据保存在 byte 数组里面,通过循环从输入流中读取数据,每次读取一部分字节,直到读取完所有上传的数据
while (totalBytesRead < formDataLength) {
byteRead = in.read(dataBytes, totalBytesRead, formDataLength);
totalBytesRead += byteRead;
}
// 根据 byte 数组创建字符串,使用指定的 UTF-8 编码将字节数组转换为字符串,方便后续对上传数据内容进行字符串相关的操作(比如提取文件名等信息)
String file = new String(dataBytes, StandardCharsets.UTF_8);
// 取得上传数据的文件名,通过对转换后的字符串进行一系列的截取操作,从包含文件名信息的字符串中提取出真正的文件名(处理了包含文件名的特定格式字符串)
String saveFile = file.substring(file.indexOf("filename=\"") + 10);
saveFile = saveFile.substring(0, saveFile.indexOf("\n"));
saveFile = saveFile.substring(saveFile.lastIndexOf("\\") + 1, saveFile.indexOf("\""));
int lastIndex = contentType.lastIndexOf("=");
// 取得数据的分隔字符串,从上传数据的类型字符串(例如 "multipart/form-data; boundary=----WebKitFormBoundaryxxx"中提取出用于分隔不同部分的边界字符串boundary
String boundary = contentType.substring(lastIndex + 1, contentType.length());
// 创建保存路径的文件名,将前面确定的文件保存目录路径与提取出的文件名拼接起来,形成完整的文件保存路径(包含文件名和目录)
String fileName = rootPath + saveFile;
int pos;
pos = file.indexOf("filename = \"");
pos = file.indexOf("\n", pos) + 1;
pos = file.indexOf("\n", pos) + 1;
pos = file.indexOf("\n", pos) + 1;
int boundaryLocation = file.indexOf(boundary, pos) - 4;
// 取得文件数据的开始的位置,通过对文件内容字符串进行一系列操作,先获取相关子字符串,再计算其字节长度来确定文件数据在整个上传数据中的起始位置
int startPos = ((file.substring(0, pos)).getBytes()).length;
int endPos = ((file.substring(0, boundaryLocation)).getBytes()).length;
File checkFile = new File(fileName);
// 检查要保存的文件是否已经存在,如果存在则输出提示信息并终止当前方法执行(直接返回)
if (checkFile.exists()) {
out.println("<p>" + saveFile + "文件已经存在.</p>");
return;
}
// 检查上传文件的目录是否存在,如果不存在则创建该目录(包括上级目录等,会递归创建),确保文件保存的目录是存在的
File fileDir = new File(rootPath);
if (!fileDir.exists()) {
fileDir.mkdirs();
}
// 创建文件的输出类,通过指定文件保存路径实例化 FileOutputStream用于将上传的数据写入到对应的文件中
fileOut = new FileOutputStream(fileName);
// 保存文件的数据,将之前读取到的字节数组中对应文件数据部分写入到文件输出流中,实现文件在服务器端的保存
fileOut.write(dataBytes, startPos, (endPos - startPos));
fileOut.close();
out.print("<b>文件上传成功</b>");
} else {
// 如果上传的数据类型不是 "multipart/form-data",则输出提示信息,告知用户需要上传该类型的文件
String content = request.getContentType();
out.print("上传的文件类型是" + content + "类型的请上传目录mutipart/form-data类型的文件");
}
} catch (Exception ex) {
// 如果在文件上传过程中出现任何异常,捕获异常并抛出一个 ServerException将原始异常的消息传递进去方便在更上层进行统一的异常处理和日志记录等操作
throw new ServerException(ex.getMessage());
}
%>
</body>
</html>