一 springboot + vue【jf】
1 上传文件调用的链接地址:
http://101.203.4.24/bas-admin/jf/common/uploadMultiFile
http://101.203.4.24/bas-admin/project/attachment/batchAdd【附件信息入库】
http://101.203.4.24/bas-admin/project/attachment/list/1003419382【附件信息列表获取】
2 下载文件调用的链接地址:
http://localhost/dev-api/jf/common/download
3 编码
1:JfCommonController.java(简版)
package com.gxchr.bas.web.controller.bas.jf;
import com.gxchr.bas.common.config.BasConfig;
import com.gxchr.bas.common.utils.file.FileUploadUtils;
import com.gxchr.bas.common.utils.file.FileUtils;
@RestController
@RequestMapping("/jf/common")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class JfCommonController {
// 多文件上传;configFilePath:linux服务器文件存储路径;
@PostMapping("/uploadMultiFile")
public void uploadMultiFile(List<MultipartFile> files) throws IOException {
Integer i = 1;
for (MultipartFile file : files) {
String filePath = FileUploadUtils.upload(configFilePath, file);
}
}
// 单文件上传;configFilePath:linux服务器文件存储路径;
@PostMapping("/upload")
public void uploadFile(MultipartFile file) throws IOException {
String fileName = FileUploadUtils.upload(configFilePath, file);
}
// 文件下载
@PostMapping("/download")
public void resourceDownload(@Valid @NotEmpty(message = "文件路径不能为空") String resource, HttpServletResponse response) throws IOException {
// 输出指定文件的byte数组:本质还是二进制数据的拷贝
FileUtils.writeBytes(downloadPath, response.getOutputStream());
}
}
2:FileUploadUtils.java:文件上传工具类(完整)
package com.gxchr.bas.common.utils.file;
import java.io.*;
import cn.hutool.core.util.StrUtil;
import com.gxchr.bas.common.config.BasConfig;
import com.gxchr.bas.common.constant.Constants;
import com.gxchr.bas.common.exception.file.InvalidExtensionException;
import com.gxchr.bas.common.utils.uuid.IdUtils;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.http.MediaType;
import org.springframework.web.multipart.MultipartFile;
import com.gxchr.bas.common.exception.file.FileNameLengthLimitExceededException;
import com.gxchr.bas.common.exception.file.FileSizeLimitExceededException;
import com.gxchr.bas.common.utils.DateUtils;
import com.gxchr.bas.common.utils.StringUtils;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
/**
* 文件上传工具类
*
* @author ruoyi
*/
public class FileUploadUtils
{
/**
* 默认大小 50M
*/
public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024;
/**
* 默认的文件名最大长度 100
*/
public static final int DEFAULT_FILE_NAME_LENGTH = 100;
/**
* 默认上传的地址
*/
private static String defaultBaseDir = BasConfig.getProfile();
public static void setDefaultBaseDir(String defaultBaseDir)
{
FileUploadUtils.defaultBaseDir = defaultBaseDir;
}
public static String getDefaultBaseDir()
{
return defaultBaseDir;
}
/**
* 以默认配置进行文件上传
*
* @param file 上传的文件
* @return 文件名称
* @throws Exception
*/
public static final String upload(MultipartFile file) throws IOException
{
try
{
return upload(getDefaultBaseDir(), file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
}
catch (Exception e)
{
throw new IOException(e.getMessage(), e);
}
}
/**
* 根据文件路径上传
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @return 文件名称
* @throws IOException
*/
public static final String upload(String baseDir, MultipartFile file) throws IOException
{
try
{
return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
}
catch (Exception e)
{
throw new IOException(e.getMessage(), e);
}
}
/**
* 文件上传
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @param allowedExtension 上传文件类型
* @return 返回上传成功的文件名
* @throws FileSizeLimitExceededException 如果超出最大大小
* @throws FileNameLengthLimitExceededException 文件名太长
* @throws IOException 比如读写文件出错时
* @throws InvalidExtensionException 文件校验异常
*/
public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension)
throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
InvalidExtensionException
{
return upload(baseDir, file, allowedExtension, null);
}
public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension, String newExtName)
throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
InvalidExtensionException
{
int fileNamelength = file.getOriginalFilename().length();
if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
{
throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
}
assertAllowed(file, allowedExtension);
String fileName = extractFilename(file, newExtName);
File desc = getAbsoluteFile(baseDir, fileName);
file.transferTo(desc);
String pathFileName = getPathFileName(baseDir, fileName);
return pathFileName;
}
/**
* 编码文件名
*/
public static final String extractFilename(MultipartFile file)
{
return extractFilename(file, null);
}
/**
* 编码文件名
*/
public static final String extractFilename(MultipartFile file, String newExtName)
{
String fileName = file.getOriginalFilename();
if(StrUtil.isBlank(newExtName)) {
newExtName = getExtension(file);
}
fileName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + newExtName;
return fileName;
}
public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
{
File desc = new File(uploadDir + File.separator + fileName);
if (!desc.exists())
{
if (!desc.getParentFile().exists())
{
desc.getParentFile().mkdirs();
}
}
return desc;
}
public static final String getPathFileName(String uploadDir, String fileName) throws IOException
{
int dirLastIndex = BasConfig.getProfile().length() + 1;
String currentDir = StringUtils.substring(uploadDir, dirLastIndex);
String pathFileName = Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName;
return pathFileName;
}
/**
* 文件大小校验
*
* @param file 上传的文件
* @return
* @throws FileSizeLimitExceededException 如果超出最大大小
* @throws InvalidExtensionException
*/
public static final void assertAllowed(MultipartFile file, String[] allowedExtension)
throws FileSizeLimitExceededException, InvalidExtensionException
{
long size = file.getSize();
if (DEFAULT_MAX_SIZE != -1 && size > DEFAULT_MAX_SIZE)
{
throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024);
}
String fileName = file.getOriginalFilename();
String extension = getExtension(file);
if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension))
{
if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION)
{
throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
fileName);
}
else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION)
{
throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
fileName);
}
else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION)
{
throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
fileName);
}
else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION)
{
throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
fileName);
}
else
{
throw new InvalidExtensionException(allowedExtension, extension, fileName);
}
}
}
/**
* 判断MIME类型是否是允许的MIME类型
*
* @param extension
* @param allowedExtension
* @return
*/
public static final boolean isAllowedExtension(String extension, String[] allowedExtension)
{
for (String str : allowedExtension)
{
if (str.equalsIgnoreCase(extension))
{
return true;
}
}
return false;
}
/**
* 获取文件名的后缀
*
* @param file 表单文件
* @return 后缀名
*/
public static final String getExtension(MultipartFile file)
{
String extension = FilenameUtils.getExtension(file.getOriginalFilename());
if (StringUtils.isEmpty(extension))
{
extension = MimeTypeUtils.getExtension(file.getContentType());
}
return extension;
}
/**
* 获取已经上传的文件
*/
public static File getUploadFile(String path) {
return new File(
BasConfig.getProfile() +
File.separator +
StringUtils.substringAfter(path, Constants.RESOURCE_PREFIX)
);
}
public static MultipartFile getMultipartFile(File file) {
FileItem item = new DiskFileItemFactory().createItem("file"
, MediaType.MULTIPART_FORM_DATA_VALUE
, true
, file.getName());
try (InputStream input = new FileInputStream(file);
OutputStream os = item.getOutputStream()) {
// 流转移
IOUtils.copy(input, os);
} catch (Exception e) {
throw new IllegalArgumentException("Invalid file: " + e, e);
}
return new CommonsMultipartFile(item);
}
}
3:FileUtis.java:文件处理工具类(完整)
package com.gxchr.bas.common.utils.file;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.gxchr.bas.common.config.BasConfig;
import com.gxchr.bas.common.utils.uuid.IdUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ArrayUtils;
import com.gxchr.bas.common.utils.DateUtils;
import com.gxchr.bas.common.utils.StringUtils;
import org.apache.commons.lang3.CharUtils;
/**
* 文件处理工具类
*
* @author ruoyi
*/
public class FileUtils
{
/**
* 类Unix路径分隔符
*/
private static final char UNIX_SEPARATOR = '/';
/**
* Windows路径分隔符
*/
private static final char WINDOWS_SEPARATOR = '\\';
public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";
/**
* 输出指定文件的byte数组
*
* @param filePath 文件路径
* @param os 输出流
* @return
*/
public static void writeBytes(String filePath, OutputStream os) throws IOException
{
FileInputStream fis = null;
try
{
File file = new File(filePath);
if (!file.exists())
{
throw new FileNotFoundException(filePath);
}
fis = new FileInputStream(file);
byte[] b = new byte[1024];
int length;
while ((length = fis.read(b)) > 0)
{
os.write(b, 0, length);
}
}
catch (IOException e)
{
throw e;
}
finally
{
IOUtils.close(os);
IOUtils.close(fis);
}
}
/**
* 写数据到文件中
*
* @param data 数据
* @return 目标文件
* @throws IOException IO异常
*/
public static String writeImportBytes(byte[] data) throws IOException
{
return writeBytes(data, BasConfig.getImportPath());
}
/**
* 写数据到文件中
*
* @param data 数据
* @param uploadDir 目标文件
* @return 目标文件
* @throws IOException IO异常
*/
public static String writeBytes(byte[] data, String uploadDir) throws IOException
{
FileOutputStream fos = null;
String pathName = "";
try
{
String extension = getFileExtendName(data);
pathName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension;
File file = FileUploadUtils.getAbsoluteFile(uploadDir, pathName);
fos = new FileOutputStream(file);
fos.write(data);
}
finally
{
IOUtils.close(fos);
}
return FileUploadUtils.getPathFileName(uploadDir, pathName);
}
/**
* 删除文件
*
* @param filePath 文件
* @return
*/
public static boolean deleteFile(String filePath)
{
boolean flag = false;
File file = new File(filePath);
// 路径为文件且不为空则进行删除
if (file.isFile() && file.exists())
{
file.delete();
flag = true;
}
return flag;
}
/**
* 文件名称验证
*
* @param filename 文件名称
* @return true 正常 false 非法
*/
public static boolean isValidFilename(String filename)
{
return filename.matches(FILENAME_PATTERN);
}
/**
* 检查文件是否可下载
*
* @param resource 需要下载的文件
* @return true 正常 false 非法
*/
public static boolean checkAllowDownload(String resource)
{
// 禁止目录上跳级别
if (StringUtils.contains(resource, ".."))
{
return false;
}
// 检查允许下载的文件规则
if (ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource)))
{
return true;
}
// 不在允许下载的文件规则
return false;
}
/**
* 下载文件名重新编码
*
* @param request 请求对象
* @param fileName 文件名
* @return 编码后的文件名
*/
public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException
{
final String agent = request.getHeader("USER-AGENT");
String filename = fileName;
if (agent.contains("MSIE"))
{
// IE浏览器
filename = URLEncoder.encode(filename, "utf-8");
filename = filename.replace("+", " ");
}
else if (agent.contains("Firefox"))
{
// 火狐浏览器
filename = new String(fileName.getBytes(), "ISO8859-1");
}
else if (agent.contains("Chrome"))
{
// google浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
else
{
// 其它浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}
/**
* 下载文件名重新编码
*
* @param response 响应对象
* @param realFileName 真实文件名
* @return
*/
public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException
{
String percentEncodedFileName = percentEncode(realFileName);
StringBuilder contentDispositionValue = new StringBuilder();
contentDispositionValue.append("attachment; filename=")
.append(percentEncodedFileName)
.append(";")
.append("filename*=")
.append("utf-8''")
.append(percentEncodedFileName);
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename");
response.setHeader("Content-disposition", contentDispositionValue.toString());
response.setHeader("download-filename", percentEncodedFileName);
}
/**
* 百分号编码工具方法
*
* @param s 需要百分号编码的字符串
* @return 百分号编码后的字符串
*/
public static String percentEncode(String s) throws UnsupportedEncodingException
{
String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
return encode.replaceAll("\\+", "%20");
}
/**
* 获取图像后缀
*
* @param photoByte 图像数据
* @return 后缀名
*/
public static String getFileExtendName(byte[] photoByte)
{
String strFileExtendName = "jpg";
if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56)
&& ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97))
{
strFileExtendName = "gif";
}
else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70))
{
strFileExtendName = "jpg";
}
else if ((photoByte[0] == 66) && (photoByte[1] == 77))
{
strFileExtendName = "bmp";
}
else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71))
{
strFileExtendName = "png";
}
return strFileExtendName;
}
/**
* 获得文件的扩展名,扩展名不带“.”
*
* @param fileName 文件名
* @return 扩展名
*/
public static String extName(String fileName) {
if (fileName == null) {
return null;
}
int index = fileName.lastIndexOf(".");
if (index == -1) {
return StringUtils.EMPTY;
} else {
String ext = fileName.substring(index + 1);
// 扩展名中不能包含路径相关的符号
return StringUtils.containsAny(ext, UNIX_SEPARATOR, WINDOWS_SEPARATOR) ? StringUtils.EMPTY : ext;
}
}
}
4 附录:JfCommonController.java(完整)
package com.gxchr.bas.web.controller.bas.jf;
import com.gxchr.bas.common.config.BasConfig;
import com.gxchr.bas.common.constant.Constants;
import com.gxchr.bas.common.core.domain.AjaxResult;
import com.gxchr.bas.common.core.domain.AjaxResultObject;
import com.gxchr.bas.common.exception.ServiceException;
import com.gxchr.bas.common.utils.StringUtils;
import com.gxchr.bas.common.utils.file.FileUploadUtils;
import com.gxchr.bas.common.utils.file.FileUtils;
import com.gxchr.bas.system.jf.domain.vo.UploadMultiFileVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* @author liangzaoyu
* @date 2023-02-15
* @description 技服通用
*/
@Api(tags = "技服-通用接口")
@RestController
@RequestMapping("/jf/common")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class JfCommonController {
@ApiOperation(value = "多文件上传")
@PostMapping("/uploadMultiFile")
@ApiImplicitParams(
{
@ApiImplicitParam(name = "files", value = "文件", required = true, dataType = "MultipartFile", dataTypeClass = List.class),
}
)
public AjaxResultObject<List<UploadMultiFileVO>> uploadMultiFile(List<MultipartFile> files) throws IOException {
if (files == null || files.isEmpty()) {
throw new ServiceException("文件不能为空");
}
// 配置里的文件路径
String configFilePath = BasConfig.getUploadPath();
// 方法已经自动生成年月日目录,不需要在配置 上传并返回新文件名称
List<UploadMultiFileVO> uploadMultiFileVOList = new ArrayList<>(files.size());
Integer i = 1;
for (MultipartFile file : files) {
String filePath = FileUploadUtils.upload(configFilePath, file);
UploadMultiFileVO uploadMultiFileVO = new UploadMultiFileVO();
uploadMultiFileVO.setIndex(i);
uploadMultiFileVO.setFilePath(filePath);
uploadMultiFileVOList.add(uploadMultiFileVO);
i++;
}
return AjaxResult.success(uploadMultiFileVOList).toAjaxResultObject();
}
@ApiOperation(value = "文件上传")
@PostMapping("/upload")
@ApiImplicitParams(
{
@ApiImplicitParam(name = "file", value = "文件", required = true, dataType = "MultipartFile", dataTypeClass = MultipartFile.class),
}
)
public AjaxResultObject<String> uploadFile(MultipartFile file) throws IOException {
if (file == null) {
throw new ServiceException("文件不能为空");
}
// 配置里的文件路径
String configFilePath = BasConfig.getUploadPath();
// 方法已经自动生成年月日目录,不需要在配置 上传并返回新文件名称
String fileName = FileUploadUtils.upload(configFilePath, file);
return AjaxResult.success(fileName).toAjaxResultObject();
}
@ApiOperation(value = "文件下载")
@PostMapping("/download")
@ApiImplicitParams(
{
@ApiImplicitParam(name = "resource", value = "文件路径", required = true, dataType = "String", dataTypeClass = String.class),
}
)
public void resourceDownload(@Valid @NotEmpty(message = "文件路径不能为空") String resource, HttpServletResponse response) throws IOException {
if (!FileUtils.checkAllowDownload(resource)) {
throw new ServiceException(StringUtils.format("资源文件({})非法,不允许下载。 ", resource));
}
// 本地资源路径:/home/bas/uploadPath
String localPath = BasConfig.getProfile();
// 数据库资源地址:/home/bas/uploadPath/upload/2023/03/02/3da3284f-d27c-4f49-bc9d-6f32a9e01bd9.xlsx
String downloadPath = localPath + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX);
// 下载名称:/home/bas/uploadPath/upload/2023/03/02/3da3284f-d27c-4f49-bc9d-6f32a9e01bd9.xlsx
String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
// APPLICATION_OCTET_STREAM_VALUE = "application/octet-stream";
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
// 下载文件名重新编码
FileUtils.setAttachmentResponseHeader(response, downloadName);
// 输出指定文件的byte数组:本质还是二进制数据的拷贝
FileUtils.writeBytes(downloadPath, response.getOutputStream());
}
}
二 springmvc多文件
1 原理
2 案例
index.jsp:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>welcom.jsp</title>
</head>
<body>
<form action="test/upload.do" method="post" enctype="multipart/form-data">
文件1:<input type="file" name="imgs"/><br>
文件2:<input type="file" name="imgs"/><br>
文件3:<input type="file" name="imgs"/><br>
<input type="submit" value="上传"/>
</form>
</body>
</html>
FileUploadController.java:
package com.bjpowernode.handler;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
@Controller
@RequestMapping("/test")
public class FileUploadController {
// @RequestParam参数校正(保证上传的文件成功转换成MultipartFile实例)
@RequestMapping("/upload.do")
public String doFileUpload(@RequestParam MultipartFile[] imgs, HttpSession session) throws IOException {
// 得自己去创建,不然报错
// String path = "D://ssmImgs";
String path = session.getServletContext().getRealPath("/ssmImgs");
for(MultipartFile img:imgs){
if(img.getSize() > 0){
// 文件类型限制
String fileName = img.getOriginalFilename();// 获取原始的名称
if(fileName.endsWith(".jpg") || fileName.endsWith(".png")){
File file = new File(path, fileName);
img.transferTo(file);
}
}
}
return "/success.jsp";
}
}
二 springmvc单文件
index.jsp:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>welcom.jsp</title>
</head>
<body>
<form action="test/upload.do" method="post" enctype="multipart/form-data">
文件:<input type="file" name="img"/><br>
<input type="submit" value="上传"/>
</form>
</body>
</html>
FileUploadController.java:
package com.bjpowernode.handler;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
@Controller
@RequestMapping("/test")
public class FileUploadController {
@RequestMapping("/upload.do")
public String doFileUpload(MultipartFile img, HttpSession session) throws IOException {
// System.out.println("img = "+img); // 一个文件都不选择(上传),这个对象也不为空
// String path = "D://ssmImgs";
String path = session.getServletContext().getRealPath("/ssmImgs");
if(img.getSize() > 0){
String fileName = img.getOriginalFilename();// 获取原始的名称
// 文件类型限制
if(fileName.endsWith(".jpg") || fileName.endsWith(".png")){
// 得自己去创建,不然报错
File file = new File(path, fileName);
img.transferTo(file);
return "/success.jsp";
}
}
return "/error.jsp";
}
}
springMVC.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--注册组件扫描器-->
<context:component-scan base-package="com.bjpowernode.handler"/>
<!--MultipartFile解析器-->
<!--名称固定:这个类直接由中央调度器DispatcherServlet.java直接调用,而在DispatcherServlet.java对这个bean的名称设置为:public static final String MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver";-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="utf-8"/><!--乱码-->
<property name="maxUploadSize" value="1048576000"/><!--总和的文件上传大小限制-->
<property name="maxUploadSizePerFile" value="1048576000"/><!--单个文件上传大小限制-->
</bean>
<!--异常处理器:文件上传超出大小-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="defaultErrorView" value="/error.jsp"/>
<property name="exceptionAttribute" value="ex"/>
</bean>
<!-- 添加mvc的注解驱动,就有MultipartFile的实现类了,并在接收文件数据后将数据封装成MultipartFile的实现类的一个对象,不懂为什么-->
<mvc:annotation-driven/>
</beans>
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>panshengbo</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springMVC.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>panshengbo</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.bjpowernode.handler</groupId>
<artifactId>01-primary-m</artifactId>
<version>1.0.0</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!--servlet依赖-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!--jsp依赖-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2.1-b03</version>
<scope>provided</scope>
</dependency>
<!--springmvc依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<!--文件上传-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 编码和编译和JDK版本 -->
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
三 struts2多文件
1 原理
Struts2 是通过拦截器实现文件上传的,而默认拦截器栈中包含了文件上传拦截器,故
若要实现文件上传功能,表单的 enctype 属性值与 method 属性值必须要如下设置:
2 案例
index.jsp:
<!DOCTYPE html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Basic Struts 2 Application - Welcome</title>
</head>
<body>
<form action="test/upLoad.action" method="post" enctype="multipart/form-data">
<%--上传多个文件--%>
文件1:<input type="file" id="img1" name="imgs"/><br>
文件2:<input type="file" id="img2" name="imgs"/><br>
文件3:<input type="file" id="img3" name="imgs"/><br>
<input type="submit" value="上传">
</form>
</body>
</html>
FileUpLoadAction.java:
package com.china.network.maven.action;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.commons.io.FileUtils;
import org.apache.struts2.ServletActionContext;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
// 第 2 步 - 创建操作类 HelloWorldAction.java
public class FileUpLoadAction {
private File[] imgs;
private String[] imgsFileName;
public String execute(){
try {
/*上传多个文件*/
// 当前没有上传文件时,imgs数据不会被创建出来
if(imgs!=null){
for(int i=0;i<imgs.length;i++){
//String path = "D://imgs"; // 物理地址
String path = ServletActionContext.getServletContext().getRealPath("/imgs"); // 服务器地址
System.out.println("path = "+path);
File file = new File(path,imgsFileName[i]);
FileUtils.copyFile(imgs[i],file);
}
return "success";
}
} catch (IOException e) {
e.printStackTrace();
}
return "fail";
}
public File[] getImgs() {
return imgs;
}
public void setImgs(File[] imgs) {
this.imgs = imgs;
}
public String[] getImgsFileName() {
return imgsFileName;
}
public void setImgsFileName(String[] imgsFileName) {
this.imgsFileName = imgsFileName;
}
}
三 struts2单文件
index.jsp:
<!DOCTYPE html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Basic Struts 2 Application - Welcome</title>
</head>
<body>
<form action="test/upLoad.action" method="post" enctype="multipart/form-data">
文件:<input type="file" id="img" name="img"/><br>
<input type="submit" value="上传">
</form>
</body>
</html>
FileUpLoadAction.java:
package com.china.network.maven.action;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.commons.io.FileUtils;
import org.apache.struts2.ServletActionContext;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
// 第 2 步 - 创建操作类 HelloWorldAction.java
public class FileUpLoadAction {
private File img;
private String imgFileName;
public String execute(){
try {
//String path = "D://imgs"; // 物理地址
String path = ServletActionContext.getServletContext().getRealPath("/imgs"); // 服务器地址
if(img!=null){
System.out.println("path = "+path);
File file = new File(path,imgFileName);
FileUtils.copyFile(img,file);
return "success";
}
} catch (IOException e) {
e.printStackTrace();
}
return "fail";
}
public File getImg() {
return img;
}
public void setImg(File img) {
this.img = img;
}
public String getImgFileName() {
return imgFileName;
}
public void setImgFileName(String imgFileName) {
this.imgFileName = imgFileName;
}
}
Strust.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<!--修改文件上传大小限制-->
<constant name="struts.multipart.maxSize" value="2097152000"/>
<package name="xxx" namespace="/test" extends="struts-default">
<action name="upLoad" class="com.china.network.maven.action.FileUpLoadAction" method="execute">
<result name="success">/WEB-INF/view/welcome.jsp</result>
<result name="fail">/WEB-INF/view/uploadErrors.jsp</result>
<interceptor-ref name="defaultStack">
<param name="fileUpload.allowedExtensions">jpg,png</param>
</interceptor-ref>
</action>
</package>
</struts>
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.china.network.maven</groupId>
<artifactId>01-primary-2-m</artifactId>
<version>1.0.0</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<struts2.version>2.3.24</struts2.version>
<log4j2.version>2.3</log4j2.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>${struts2.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j2.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j2.version}</version>
</dependency>
<!--servlet依赖-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!--jsp依赖-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2.1-b03</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Basic Struts2</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- 配置struts2启动项 -->
<filter>
<filter-name>struts</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
四 servlet 文件下载功能实现_bilibili
****************************文件上传与下载 begin****************************
1、提交表单满足条件
提交表单:发送的请求方式必须是post;
表单属性enctype:值设置为:enctype="multipart/form-data"
2、导入文件支持包
<!-- 文件上传支持 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
3、文件上传相关的API
- FileItem【相当于产品】: FileItem接口用于封装表单字段元素的数据,一个表单字段元素对应一个FileItem对象。
- DiskFileItemFactory【生产产品的工厂】:用于将请求实体中的每一个文件封装成单独的FileItem对象。
- ServletFileUpload【生产产品的机械】:是Apache组件处理文件上传的核心高级类,通过parseRequest()方法将表单提交的数据封装成FileItem对象。
- isFormField()方法:用于判断FileItem类的对象封装的数据是一个普通文本表单字段还是一个文件表单字段;如果是一个普通表单字段则返回值为true,否则返回值为false。
****************************文件上传与下载 end****************************
上传页面:pic.jsp
<%@ page language="java" import="java.util.*" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" autoFlush="false" buffer="16kb"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>文件上传页面</title>
</head>
<body>
<fieldset>
<legend>文件上传窗口</legend>
<form action="upload" method="post" enctype="multipart/form-data">
<table width="600px">
<tr>
<td>上传者</td><td><input type="text" name="name" /></td>
</tr>
<tr>
<td>上传文件</td><td><input type="file" name="myfile" /></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="上传按钮"/></td>
</tr>
</table>
</form>
</fieldset>
</body>
</html>
上传servlet:UploadServlet.java
package com.qst.servlet;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;
import javax.servlet.ServletException;
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;
public class UploadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public void service(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
// 设置编码集(解码)
request.setCharacterEncoding("UTF-8");
// 设置响应的编码集
response.setContentType("text/html;charset=utf-8");
//创建工厂
DiskFileItemFactory factory=new DiskFileItemFactory();
File f=new File("E:\\tmp");
if(!f.exists()){
f.mkdirs();
}
//设置文件的缓存路径
factory.setRepository(f);
//创建ServletFileUpload组件
ServletFileUpload fileupload=new ServletFileUpload(factory);
fileupload.setHeaderEncoding("UTF-8");
//解析request
try {
List<FileItem> fileItems=fileupload.parseRequest(request);
//遍历集合
for(FileItem fileItem:fileItems){
//判断是否为普通字段
if(fileItem.isFormField()){
//获取字段名和字段值
String name=fileItem.getFieldName();
String value=fileItem.getString("UTF-8");
System.out.println("上传者:"+value);
}else{
//获取上传的文件名
String fileName=fileItem.getName();
int index=fileName.lastIndexOf("\\");
if(index!=-1) {
fileName=fileName.substring(index+1);
}
System.out.println("文件名称:"+fileName);
//创建UUID产生的随机字符串
String result=UUID.randomUUID().toString();
fileName=result+fileName;
String webPath="/upload/";
String path=request.getSession().getServletContext().getRealPath(webPath+"\\"+fileName);
System.out.println(path+"@@@@@@@@@");
File file=new File(path);
file.getParentFile().mkdirs();
file.createNewFile();
//获得file对象的输出流
FileOutputStream out=new FileOutputStream(file);
//获取fileItem的输入流
InputStream in=fileItem.getInputStream();
//实现文件的上传(本质是复制)
byte[]buffer=new byte[1024];
int len=-1;
while((len=in.read(buffer))!=-1){
out.write(buffer,0,len);
}
in.close();
out.close();
//删除fileItem对象
fileItem.delete();
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
request.getRequestDispatcher("/show").forward(request, response);
}
}
显示servlet:ShowServlet.java
package com.qst.servlet;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ShowServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public void service(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
// 设置编码集(解码)
request.setCharacterEncoding("UTF-8");
// 设置响应的编码集
response.setContentType("text/html;charset=utf-8");
//根据逻辑路径获取物理路径
String path= request.getSession().getServletContext().getRealPath("/upload/");
File file=new File(path);
File[] files= file.listFiles();
List<String>fileNames=new ArrayList<String>();
for(File f:files){
String fileName=f.getName();
fileNames.add(fileName);
}
request.setAttribute("fileNames", fileNames);
//转发
request.getRequestDispatcher("/show.jsp").forward(request, response);
}
}
显示页面:show.jsp
<%@ page language="java" import="java.util.*" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" autoFlush="false" buffer="16kb"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>文件展示页面</title>
</head>
<body>
<c:forEach var="fileName" items="${fileNames}">
<a href="download?fileName=${fileName}">${fileName}</a><br/>
<a href="download?fileName=${fileName}"><img alt="" src="download?fileName=${fileName}" width="200" height="200"></a><br/><br/>
</c:forEach>
</body>
</html>
下载servlet:DownloadServlet.java
package com.qst.servlet;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class DownloadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public void service(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
// 设置编码集(解码)
request.setCharacterEncoding("UTF-8");
// 设置响应的编码集
response.setContentType("text/html;charset=utf-8");
String fileName=request.getParameter("fileName");
//通知浏览器以下载的方式打开
response.addHeader("Content-Type", "application/octet-stream");
response.addHeader("Content-Disposition","attachment;filename="+URLEncoder.encode(fileName));
//通过文件流读取文件
String path= request.getSession().getServletContext().getRealPath("/upload/");
//针对要下载的文件创建了输入流
FileInputStream in=new FileInputStream(path+"\\"+fileName);
//获取response的输出流
ServletOutputStream out= response.getOutputStream();
byte[]buffer=new byte[1024];
int len=-1;
while((len=in.read(buffer))!=-1){
out.write(buffer, 0, len);
}
in.close();
out.close();
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<welcome-file-list>
<welcome-file>pic.jsp</welcome-file>
</welcome-file-list>
<servlet>
<description></description>
<display-name>UploadServlet</display-name>
<servlet-name>UploadServlet</servlet-name>
<servlet-class>com.qst.servlet.UploadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UploadServlet</servlet-name>
<url-pattern>/upload</url-pattern>
</servlet-mapping>
<servlet>
<description></description>
<display-name>ShowServlet</display-name>
<servlet-name>ShowServlet</servlet-name>
<servlet-class>com.qst.servlet.ShowServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ShowServlet</servlet-name>
<url-pattern>/show</url-pattern>
</servlet-mapping>
<servlet>
<description></description>
<display-name>DownloadServlet</display-name>
<servlet-name>DownloadServlet</servlet-name>
<servlet-class>com.qst.servlet.DownloadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DownloadServlet</servlet-name>
<url-pattern>/download</url-pattern>
</servlet-mapping>
</web-app>
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.qst</groupId>
<artifactId>w_chapter004</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<!-- JSP标准标签库 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<!-- 文件上传支持 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
</dependencies>
</project>