java实现文件的上传下载
一、本地上传与下载、搭建ftp服务器,ftp上传与下载
- 直接上代码
import com.skweb.qt.common.ResponseResult;
import com.skweb.qt.entity.File;
import com.skweb.qt.entity.MyProps;
import com.skweb.qt.service.FileService;
import com.skweb.qt.utils.UploadUtil;
import io.swagger.annotations.*;
import org.apache.commons.net.ftp.FTPClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
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.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;
@RestController
@RequestMapping("/file")
@Api(tags = "本地和ftp服务器的上传与下载功能")
public class FileController {
private final static Logger logger = LoggerFactory.getLogger(FileController.class);
@Autowired
private MyProps myProps;
@Autowired
FileService fileService;
/**
* @Author Eric
*/
@ApiOperation(value = "获取文件列表", httpMethod = "GET")
@ApiResponses({ @ApiResponse(code = 1, message = "成功"), @ApiResponse(code = 0, message = "失败") })
@GetMapping(value = "/getFileList")
public ResponseResult getFileList(){
return fileService.getFileList();
}
/**
* @Author Eric
*/
@ApiOperation(value = "上传并保存文件", httpMethod = "POST")
@ApiImplicitParams({ @ApiImplicitParam(name = "excelfile", value = "文件", dataType = "CommonsMultipartFile") })
@ApiResponses({ @ApiResponse(code = 1, message = "成功"), @ApiResponse(code = 0, message = "失败") })
@PostMapping(value = "uploadAndSave", headers = ("content-type=multipart/*"))
public String save(@ApiParam(value = "file", required = true) MultipartFile file,
HttpServletRequest request) {
if(file.isEmpty()){
return "上传失败,文件为空";
}
//生成唯一文件名
String fileName = UploadUtil.generateFileName(file.getOriginalFilename());
int size = (int) file.getSize();
logger.info("-------上传文件:"+fileName + ",大小为:" + size);
java.io.File dest = new java.io.File(myProps.getFilePath() + "/" + fileName);
if(!dest.getParentFile().exists()){ //判断文件父目录是否存在
dest.getParentFile().mkdir();
}
try {
file.transferTo(dest); //保存文件
//解析存parseFile
String jsonFileTree = fileService.parseFile(dest, myProps.getUnzipPath(), file.getOriginalFilename());
//文件名称、路径存库
String save = fileService.save(fileName, dest.getPath(),jsonFileTree);
return save;
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "上传失败,非法状态异常";
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "上传失败,服务器异常";
}
}
/**
* @Author Eric
*/
@ApiOperation(value = "下载文件", httpMethod = "GET")
@ApiImplicitParams({ @ApiImplicitParam(name = "id", value = "文件ID", dataType = "String"),
@ApiImplicitParam(name = "filePath", value = "文件完整路径", dataType = "String"),
@ApiImplicitParam(name = "filename", value = "文件名称", dataType = "String")})
@RequestMapping("/download")
public Object download(HttpServletResponse response,Integer id,String filePath,String filename) throws UnsupportedEncodingException{
if(id==null&&!(filePath.equals("")&&filePath==null)){
//testzip\testnextfile\nextnextfile\安阳市安阳县安阳村.json
filePath=myProps.getUnzipPath()+ filePath;
}else{
File fileById = fileService.getFileById(id);
filename =fileById.getName();
filePath = fileById.getPath();
}
java.io.File file = new java.io.File(filePath);
if(file.exists()){ //判断文件父目录是否存在
response.setContentType("application/vnd.ms-excel;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
// response.setContentType("application/force-download");
response.setHeader("Content-Disposition", "attachment;fileName=" + java.net.URLEncoder.encode(filename,"UTF-8"));
byte[] buffer = new byte[1024];
FileInputStream fis = null; //文件输入流
BufferedInputStream bis = null;
OutputStream os = null; //输出流
try {
os = response.getOutputStream();
fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
int i = bis.read(buffer);
while(i != -1){
os.write(buffer);
i = bis.read(buffer);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
logger.info("----------文件下载:---" + java.net.URLEncoder.encode(filename,"UTF-8"));
try {
bis.close();
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
/**
* @Author Eric
* */
@ApiOperation(value = "FTP上传并保存文件", httpMethod = "POST")
@ApiImplicitParams({ @ApiImplicitParam(name = "excelfile", value = "文件", dataType = "CommonsMultipartFile") })
@ApiResponses({ @ApiResponse(code = 1, message = "成功"), @ApiResponse(code = 0, message = "失败") })
@PostMapping("/ftpUploadAndSave")
public String ftpUploadAndSave(@ApiParam(value = "file", required = true) MultipartFile file,
HttpServletRequest request) throws Exception {
if(file.isEmpty()){
return "上传失败,文件为空!";
}
FTPClient ftp = new FTPClient();
ftp.connect(myProps.getFtpIp(), myProps.getFtpPort());
boolean login = ftp.login("EDZ", "123456");
if(!login){
return "上传失败,ftp用户名或密码错误!";
}
ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
ftp.enterLocalPassiveMode();
ftp.setCharset(Charset.forName("UTF-8"));
ftp.setControlEncoding("UTF-8");
try {
String fileName = UploadUtil.generateFileName(file.getOriginalFilename());
OutputStream os = ftp.storeFileStream(new String(fileName.getBytes("GBK"),"iso-8859-1"));
InputStream inputStream = file.getInputStream();
byte[] b = new byte[1024];
int len = 0;
while ((len = inputStream.read(b)) != -1) {
os.write(b,0,len);
}
os.close();
inputStream.close();
ftp.logout();
//解析存parseFile
java.io.File dest = new java.io.File(myProps.getFtpPath() + "/" + fileName);
if(!dest.getParentFile().exists()){ //判断文件父目录是否存在
dest.getParentFile().mkdir();
}
file.transferTo(dest); //保存文件
String jsonFileTree = fileService.parseFile(dest, myProps.getFtpUnzipPath(), file.getOriginalFilename());
//存库
fileService.save(fileName,"ftp://"+myProps.getFtpIp()+":"+myProps.getFtpPort()+"/"+fileName,jsonFileTree);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "上传到ftp服务器成功!";
}
/**
* @Author Eric
*/
@ApiOperation(value = "ftp下载文件", httpMethod = "GET")
@ApiImplicitParams({ @ApiImplicitParam(name = "id", value = "原文件ID", dataType = "String"),
@ApiImplicitParam(name = "filePath", value = "文件完整路径", dataType = "String") })
@RequestMapping("/ftpDownload")
public String ftpDownload(HttpServletResponse response,Integer id,String filePath) throws Exception{
if(id==null&&!(filePath.equals("")&&filePath==null)){
//处理ftp服务器编码问题
List<String> fnList = Arrays.asList(filePath.split("/"));
StringBuffer sb=new StringBuffer("");
for(String fn:fnList){
sb.append(URLEncoder.encode(fn, "GBK")).append("/");
}
return myProps.getFtpUnzipUrl()+sb.toString();
//return myProps.getFtpUnzipUrl()+ filePath;
}else {
String name = fileService.getFileById(id).getName();
return "ftp://"+myProps.getFtpIp()+":"+myProps.getFtpPort()+"/"+URLEncoder.encode(name,"GBK");
}
}
}
import com.alibaba.fastjson.JSONObject;
import com.skweb.qt.common.ResponseEnum;
import com.skweb.qt.common.ResponseResult;
import com.skweb.qt.entity.File;
import com.skweb.qt.mapper.FileMapper;
import com.skweb.qt.service.FileService;
import com.skweb.qt.utils.UploadUtil;
import com.skweb.qt.vo.FileTree;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.*;
@Service
public class FileServiceImpl implements FileService {
@Autowired
FileMapper fileMapper;
List <FileTree> node=new LinkedList();
@Override
public String parseFile(java.io.File dest,String unzipPath,String fileName)throws IOException {
//先解压
UploadUtil.unzipFile(dest, unzipPath);
node.removeAll(node);
int level=0;
List<String> fnList = Arrays.asList(fileName.split("\\."));
List<FileTree> files=getFile(unzipPath+fnList.get(0),1,level);
List<FileTree> fileTree = getFileTree(files);
FileTree ft=new FileTree();
ft.setId(0);
ft.setpId(0);
ft.setHasChildren(true);
ft.setChildren(fileTree);
ft.setName(fnList.get(0));
return JSONObject.toJSONString(ft);
}
//递归成树
private List<FileTree> getFileTree(List<FileTree> files) {
List<FileTree> fileTreeList=new LinkedList<>();
for(FileTree ft:files){
//[{"id":1,"name":"testnextfile","pId":0},{"id":11,"name":"安阳市安阳县.json","pId":1},
// {"id":2,"name":"安阳市.json","pId":0},{"id":3,"name":"鹤壁市.json","pId":0}]
if(ft.isHasChildren()&&ft.getpId()==0){
List<FileTree> childrenTree = getChildrenTree(ft, files);
ft.setChildren(childrenTree);
fileTreeList.add(ft);
}else {
if(ft.getpId()==0){
fileTreeList.add(ft);
}
}
}
return fileTreeList;
}
private List<FileTree> getChildrenTree(FileTree ft,List<FileTree> files) {
List<FileTree> ftList=new LinkedList<>();
for(FileTree f:files){
if(f.isHasChildren()&&ft.getId()!=f.getId()&&f.getId()>ft.getId()){
if(f.getpId()==ft.getId()){
List<FileTree> childrenTree = getChildrenTree(f, files);
f.setChildren(childrenTree);
ftList.add(f);
}
}else{
if(f.getpId()==ft.getId()){
ftList.add(f);
}
}
}
return ftList;
}
private List<FileTree> getFile(String path,int id,int pid) {
java.io.File file = new java.io.File(path);
if(file.exists()) {
java.io.File[] array = file.listFiles();
List fileList = Arrays.asList(array);
//对读到的本地文件夹进行排序
Collections.sort(fileList, new Comparator<java.io.File>() {
@Override
public int compare(java.io.File o1, java.io.File o2) {
if (o1.isDirectory() && o2.isFile())
return -1;
if (o1.isFile() && o2.isDirectory())
return 1;
return o1.getName().compareTo(o2.getName());
}
});
for (int i = 0; i < array.length; i++) {
FileTree tree = new FileTree();
tree.setpId(pid);
tree.setId(id);
tree.setName(array[i].getName());
//判断是否为文件夹,是的话进行递归
if (array[i].isDirectory()) {
tree.setHasChildren(true);
node.add(tree);
//进行递归,此时的pid为上一级的id
getFile(array[i].getPath(), id * 10 + 1 + i, id);
id++;
} else {
tree.setHasChildren(false);
node.add(tree);
id++;
}
}
}
else
{
System.out.println("文件不存在");
}
return node;
}
@Override
public ResponseResult getFileList() {
ResponseResult res=new ResponseResult();
List<File> fileList = fileMapper.getFileList();
res.setTotal((long) fileList.size());
res.setCode(ResponseEnum.SUCCESS.getCode());
res.setData(fileList);
return res;
}
@Override
public String save(String name, String path,String fileTree) {
File test=new File();
test.setName(name);
test.setPath(path);
int save = fileMapper.save(name, path,fileTree);
if(save>0){
return "上传成功!";
}
return "长传失败!";
}
@Override
public File getFileById(Integer id) {
return fileMapper.getFileById(id);
}
}
2.存储路径写配置文件
myprops:
fileUrl: http://127.0.0.1:8088/
filePath: D:\\upload\\
unzipPath: D:\\upload\\unzipFile\\
ftpIp: 127.0.0.1
ftpPort: 21
ftpUsername: EDZ
ftpPassword: 123456
ftpPath: D:\\ftp
ftpUnzipPath: D:\\ftp\\unzipFile\\
ftpUnzipUrl: ftp://127.0.0.1/unzipFile/
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix="myprops") //接收application-dev.yml中的myProps下面的属性
public class MyProps {
public String fileUrl;
public String filePath;
public String unzipPath;
public String ftpIp;
public int ftpPort;
public String ftpUsername;
public String ftpPassword;
public String ftpPath;
public String ftpUnzipPath;
public String ftpUnzipUrl;
public String getFileUrl() {
return fileUrl;
}
public void setFileUrl(String fileUrl) {
this.fileUrl = fileUrl;
}
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public String getUnzipPath() {
return unzipPath;
}
public void setUnzipPath(String unzipPath) {
this.unzipPath = unzipPath;
}
public String getFtpIp() {
return ftpIp;
}
public void setFtpIp(String ftpIp) {
this.ftpIp = ftpIp;
}
public int getFtpPort() {
return ftpPort;
}
public void setFtpPort(int ftpPort) {
this.ftpPort = ftpPort;
}
public String getFtpUsername() {
return ftpUsername;
}
public void setFtpUsername(String ftpUsername) {
this.ftpUsername = ftpUsername;
}
public String getFtpPassword() {
return ftpPassword;
}
public void setFtpPassword(String ftpPassword) {
this.ftpPassword = ftpPassword;
}
public String getFtpPath() {
return ftpPath;
}
public void setFtpPath(String ftpPath) {
this.ftpPath = ftpPath;
}
public String getFtpUnzipPath() {
return ftpUnzipPath;
}
public void setFtpUnzipPath(String ftpUnzipPath) {
this.ftpUnzipPath = ftpUnzipPath;
}
public String getFtpUnzipUrl() {
return ftpUnzipUrl;
}
public void setFtpUnzipUrl(String ftpUnzipUrl) {
this.ftpUnzipUrl = ftpUnzipUrl;
}
}
- 配置本地上传文件大小,以免上传过大会报异常
import org.springframework.boot.web.servlet.MultipartConfigFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.unit.DataSize;
import javax.servlet.MultipartConfigElement;
@Configuration
public class UploadConfig {
@Bean
public MultipartConfigElement multipartConfigElement() {
MultipartConfigFactory factory = new MultipartConfigFactory();
//单个文件最大
factory.setMaxFileSize(DataSize.ofGigabytes(1L)); //GB
/// 设置总上传数据总大小
factory.setMaxRequestSize(DataSize.ofGigabytes(1L));
return factory.createMultipartConfig();
}
}
- 上传工具类
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.compress.utils.IOUtils;
import java.io.*;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class UploadUtil {
public static String generateFileName(String originalFilename){
List<String> fnList = Arrays.asList(originalFilename.split("\\."));
//文件重命名:原名称+时间戳+后缀
String fileName=fnList.get(0)+new Timestamp(System.currentTimeMillis()).getTime()+"."+fnList.get(1);
return fileName;
}
public static List<String> unzipFile(File zipFile, String unzipPath)throws IOException {
//先解压
List<String> fileNames = new ArrayList<>();
String fileEncoding = null;
try {
fileEncoding = checkEncoding(zipFile);
} catch (IOException e1) {
e1.printStackTrace();
}
String fileEncoding1 = (fileEncoding != null) ? fileEncoding : "UTF-8";
try (ZipArchiveInputStream zais = new ZipArchiveInputStream(new BufferedInputStream(new FileInputStream(zipFile), 4096), fileEncoding1)) {
ZipArchiveEntry entry = null;
while ((entry = zais.getNextZipEntry()) != null) {
//遍历压缩包,如果进行有选择解压,可在此处进行过滤
File tmpFile = new File(unzipPath, entry.getName());
if (entry.isDirectory()) {
tmpFile.mkdirs();
} else {
fileNames.add(entry.getName());
File file = new File(tmpFile.getAbsolutePath());
if (!file.exists()) {
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
}
try (OutputStream os = new BufferedOutputStream(new FileOutputStream(tmpFile), 4096)) {
IOUtils.copy(zais, os);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return fileNames;
}
//判断字符编码
private static String checkEncoding(File file) throws IOException {
InputStream in = new FileInputStream(file);
byte[] b = new byte[3];
try {
int i = in.read(b);
} catch (IOException e) {
e.printStackTrace();
} finally {
in.close();
}
if (b[0] == -1 && b[1] == -2) {
return "UTF-16";
} else if (b[0] == -2 && b[1] == -1) {
return "Unicode";
} else if (b[0] == -17 && b[1] == -69 && b[2] == -65) {
return "UTF-8";
} else {
return "GBK";
}
}
//
// public static List<String> getFileTree(String unzipPath) {
// List<String>filePaths = new ArrayList<>();
// LinkedList<File> list = new LinkedList<File>();
// File dir = new File(unzipPath);
// File[] file = dir.listFiles();
//
// for (int i = 0; i < file.length; i++) {
// if (file[i].isDirectory()) {
// // 把第一层的目录,全部放入链表
// list.add(file[i]);
// }
// filePaths.add(file[i].getAbsolutePath());
// }
// // 循环遍历链表
// while (!list.isEmpty()) {
// // 把链表的第一个记录删除
// File tmp = list.removeFirst();
// // 如果删除的目录是一个路径的话
// if (tmp.isDirectory()) {
// // 列出这个目录下的文件到数组中
// file = tmp.listFiles();
// if (file == null) {// 空目录
// continue;
// }
// // 遍历文件数组
// for (int i = 0; i < file.length; ++i) {
// if (file[i].isDirectory()) {
// // 如果遍历到的是目录,则将继续被加入链表
// list.add(file[i]);
// }
// filePaths.add(file[i].getAbsolutePath());
// }
// }
// }
// return filePaths;
// }
}