Java實現文件分片上傳接口的示例代碼
更新時間:2022年07月25日 15:33:15 作者:春春&
這篇文章主要為大家詳細介紹了如何利用Java語言實現文件分片上傳的功能,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起了解一下
java后端分片上傳接口
文件上傳工具--FileUtil
package com.youmejava.chun.util;
import lombok.Data;
import org.apache.tomcat.util.http.fileupload.FileUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* 文件工具
*/
@Data
public class FileUtil {
private List<File> filelist;//文件列表
private String strPath;//路徑
public FileUtil() {
}
public FileUtil(List<File> filelist, String strPath) {
this.filelist = filelist;
this.strPath = strPath;
getFileList(this.strPath);
}
/**
* 獲取文件列表
* @param strPath
* @return
*/
public List<File> getFileList(String strPath) {
File dir = new File(strPath);
File[] files = dir.listFiles(); // 該文件目錄下文件全部放入數組
if (files != null) {
for (int i = 0; i < files.length; i++) {
String fileName = files[i].getName();
if (files[i].isDirectory()) { // 判斷是文件還是文件夾
getFileList(files[i].getAbsolutePath()); // 獲取文件絕對路徑
} else { // 判斷文件名
String strFileName = files[i].getAbsolutePath();
// System.out.println("---" + strFileName);
filelist.add(files[i]);
}
}
}
return filelist;
}
/**
* 合并文件
* @param from
* @param to
* @throws IOException
*/
public static void mergeFile(String from, String to) throws IOException {
File t = new File(to);
FileInputStream in = null;
FileChannel inChannel = null;
System.out.println("t "+t);
FileOutputStream out = new FileOutputStream(t,true);
FileChannel outChannel = out.getChannel();
File f = new File(from);
System.out.println("f "+f.isDirectory());
// 獲取目錄下的每一個文件名,再將每個文件一次寫入目標文件
if (f.isDirectory()) {
List<File> list = getAllFileAndSort(from);
System.out.println("sortlist "+list);
// 記錄新文件最后一個數據的位置
long start = 0;
for (File file : list) {
in = new FileInputStream(file);
inChannel = in.getChannel();
// 從inChannel中讀取file.length()長度的數據,寫入outChannel的start處
outChannel.transferFrom(inChannel, start, file.length());
start += file.length();
in.close();
inChannel.close();
}
}
out.close();
outChannel.close();
}
/**
* 所有文件排序
* @param dirPath 文件根目錄路徑
* @return
*/
public static List<File> getAllFileAndSort(String dirPath) {
File dirFile = new File(dirPath);
File[] listFiles = dirFile.listFiles();
List<File> list = Arrays.asList(listFiles);
Collections.sort(list, (o1, o2) -> {
String _str=o1.getName().split("\\.")[0];
String _num=_str.split("_")[1];
String _str2=o2.getName().split("\\.")[0];
String _num2=_str2.split("_")[1];
return Integer.parseInt(_num) - Integer.parseInt(_num2);
});
return list;
}
/**
* 刪除文件夾
* 刪除文件夾需要把包含的文件及文件夾先刪除,才能成功
* https://blog.csdn.net/m0_57640408/article/details/120774050
* @param directory 文件夾名
* @return 刪除成功返回true,失敗返回false
*/
public static boolean deleteDirectory(String directory) {
// directory不以文件分隔符(/或\)結尾時,自動添加文件分隔符,不同系統(tǒng)下File.separator方法會自動添加相應的分隔符
if (!directory.endsWith(File.separator)) {
directory = directory + File.separator;
}
File directoryFile = new File(directory);
// 判斷directory對應的文件是否存在,或者是否是一個文件夾
if (!directoryFile.exists() || !directoryFile.isDirectory()) {
System.out.println("文件夾刪除失敗,文件夾不存在" + directory);
return false;
}
boolean flag = true;
// 刪除文件夾下的所有文件和文件夾
File[] files = directoryFile.listFiles();
for (int i = 0; i < files.length; i++) { // 循環(huán)刪除所有的子文件及子文件夾
// 刪除子文件
if (files[i].isFile()) {
flag = deleteFile(files[i].getAbsolutePath());
if (!flag) {
break;
}
} else { // 刪除子文件夾
flag = deleteDirectory(files[i].getAbsolutePath());
if (!flag) {
break;
}
}
}
if (!flag) {
System.out.println("刪除失敗");
return false;
}
// 最后刪除當前文件夾
if (directoryFile.delete()) {
System.out.println("刪除成功:" + directory);
return true;
} else {
System.out.println("刪除失?。? + directory);
return false;
}
}
/**
* 刪除文件
*
* @param fileName 文件名
* @return 刪除成功返回true,失敗返回false
*/
public static boolean deleteFile(String fileName) {
File file = new File(fileName);
if (file.isFile() && file.exists()) {
file.delete();
System.out.println("刪除文件成功:" + fileName);
return true;
} else {
System.out.println("刪除文件失?。? + fileName);
return false;
}
}
}分片上傳文件接口
?package com.youmejava.chun.commoninterface;
import com.youmejava.chun.util.FileUtil;
import com.youmejava.chun.util.ResultVo;
import com.youmejava.chun.util.StringUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authc.ExpiredCredentialsException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/api/apiSystem/upload")
@Api(value = "文件上傳", tags = "文件上傳")
public class UploadController {
@Value("${filePath1}")
private String filePath;
@PostMapping("/register")
@ApiOperation(value = "文件注冊", notes = "文件注冊")
@ApiImplicitParams({@ApiImplicitParam(value = "哈希值", name = "hash", required = true, paramType = "body")})
public ResultVo register(@RequestBody Map<String, Object> map) {
System.out.println("hash: " + map.get("hash"));
if (!StringUtil.isNotBlankAndNull(map.get("hash").toString())) {
// return ResultVo.failure("哈希值不可為空");
throw new ExpiredCredentialsException("哈希值不可為空!");
}
String _filePath=filePath;
if (!_filePath.endsWith("/")) {
_filePath+="/";
}
// String _pathStr = "C:\\Users\\JH-rent\\Desktop\\java啟動文件\\test" + "\\" + map.get("hash");
String _pathStr=_filePath+map.get("hash");
//創(chuàng)建不同的文件夾目錄
File file = new File(_pathStr);
//判斷文件夾是否存在
if (!file.exists()) {
//如果文件夾不存在,則創(chuàng)建新的的文件夾
file.mkdirs();
}
File f = new File(_pathStr);
// 檢查目錄是否已上傳過文件,如果上傳過,返回上傳個數
if (f.isDirectory()) {
File dirFile = new File(_pathStr);
File[] listFiles = dirFile.listFiles();
List<File> list = Arrays.asList(listFiles);
if (list == null&&list.size()>0) {
Map<String, Object>map1=new HashMap<>();
map1.put("number",list.size());
return ResultVo.success(map1);
}
}
return ResultVo.success();
}
@PostMapping("/uploadFile")
@ResponseBody
@ApiOperation(value = "上傳文件", notes = "上傳文件")
@ApiImplicitParams({@ApiImplicitParam(value = "哈希值", name = "hash", required = true, paramType = "body"), @ApiImplicitParam(value = "文件流", name = "file", required = true, paramType = "body"), @ApiImplicitParam(value = "文件名稱", name = "fileName", required = true, paramType = "body"),})
public ResultVo uploadFile(HttpServletRequest request) {
MultipartHttpServletRequest params = ((MultipartHttpServletRequest) request);
List<MultipartFile> files = ((MultipartHttpServletRequest) request).getFiles("file");
String _fileName = params.getParameter("fileName");
String _hash = params.getParameter("hash");
if (!StringUtil.isNotBlankAndNull(_hash)) {
throw new ExpiredCredentialsException("哈希值不可為空!");
}
if (!StringUtil.isNotBlankAndNull(_fileName)) {
throw new ExpiredCredentialsException("文件名稱不可為空!");
}
// System.out.println("_fileName: " + _fileName);
// System.out.println("_hash: " + _hash);
// System.out.println("files: " + files);
// System.out.println(params.getParameter("file"));
// String _pathStr = "C:\\Users\\JH-rent\\Desktop\\java啟動文件\\test" + "\\" + _hash + "\\";
String _filePath=filePath;
if (!_filePath.endsWith("/")) {
_filePath+="/";
}
String _pathStr =_filePath+_hash+"/";
FileOutputStream fileOut = null;
//寫入到文件(注意文件保存路徑的后面一定要加上文件的名稱)
try {
fileOut = new FileOutputStream(_pathStr + _fileName);
BufferedOutputStream bos = new BufferedOutputStream(fileOut);
BufferedInputStream bis = null;
for (MultipartFile file : files) {
// file.transferTo(new File(_pathStr + file.getOriginalFilename()));
// System.out.println(file.getInputStream());
bis = new BufferedInputStream(file.getInputStream());
}
byte[] buf = new byte[4096];
int length = bis.read(buf);
//保存文件
while (length != -1) {
bos.write(buf, 0, length);
length = bis.read(buf);
}
bos.close();
bis.close();
return ResultVo.success();
} catch (Exception e) {
e.printStackTrace();
return ResultVo.failure(e.getMessage());
}
}
@GetMapping("/getMergeFile")
@ApiOperation(value = "獲取合并文件", notes = "獲取合并文件")
@ApiImplicitParams({@ApiImplicitParam(value = "哈希值", name = "hash", required = true, dataType = "String"), @ApiImplicitParam(value = "文件名稱", name = "fileName", required = true, dataType = "String")})
public ResultVo getMergeFile(@RequestParam(value = "hash") String hash, @RequestParam(value = "fileName") String fileName) {
// String _pathStr = "C:\\Users\\JH-rent\\Desktop\\java啟動文件\\test" + "\\" + hash + "\\";
// String _pathStr1 = "C:\\Users\\JH-rent\\Desktop\\java啟動文件\\test";
String _filePath=filePath;
if (!_filePath.endsWith("/")) {
_filePath+="/";
}
String _pathStr = _filePath + hash + "/";
String _pathStr1 = _filePath;
try {
// if (!_pathStr1.endsWith("\\")) {
// _pathStr1 += "\\";
// }
_pathStr1 += fileName;
FileUtil.mergeFile(_pathStr, _pathStr1);
//合并成功刪除加密文件
FileUtil.deleteDirectory(_pathStr);
} catch (IOException e) {
e.printStackTrace();
}
Map<String, Object>map=new HashMap<>();
map.put("fileUrl",_pathStr1);
return ResultVo.success(map);
}
}前端分片
單個文件下載或者分批壓縮多個文件下載
import JSZip from "jszip";
import fileSaver from "file-saver";
import axios from 'axios'
import {
Message,
Notification
} from "element-ui";
//下載單個文件
export const downloadSingleFile = (url, filename) => {
filename = filename || "文件名";
let suffix = /\.([0-9a-zA-Z]+)$/i.exec(url)[1];
const file_type = {
'doc': 'application/msword',
'bin': 'application/octet-stream',
'exe': 'application/octet-stream',
'so': 'application/octet-stream',
'dll': 'application/octet-stream',
'pdf': 'application/pdf',
'ai': 'application/postscript',
'xls': 'application/vnd.ms-excel',
'ppt': 'application/vnd.ms-powerpoint',
'dir': 'application/x-director',
'js': 'application/x-javascript',
'swf': 'application/x-shockwave-flash',
'xhtml': 'application/xhtml+xml',
'xht': 'application/xhtml+xml',
'zip': 'application/zip',
'mid': 'audio/midi',
'midi': 'audio/midi',
'mp3': 'audio/mpeg',
'rm': 'audio/x-pn-realaudio',
'rpm': 'audio/x-pn-realaudio-plugin',
'wav': 'audio/x-wav',
'bmp': 'image/bmp',
'gif': 'image/gif',
'jpeg': 'image/jpeg',
'jpg': 'image/jpeg',
'png': 'image/png',
'css': 'text/css',
'html': 'text/html',
'htm': 'text/html',
'txt': 'text/plain',
'xsl': 'text/xml',
'xml': 'text/xml',
'mpeg': 'video/mpeg',
'mpg': 'video/mpeg',
'avi': 'video/x-msvideo',
'movie': 'video/x-sgi-movie',
}
return new Promise((resolve, reject) => {
console.log(url, "url");
axios
.get(url, {
responseType: 'blob',
})
.then((res) => {
const blob = new Blob([res.data], {
type: file_type[suffix]
}) // 構造一個blob對象來處理數據,并設置文件類型
if (window.navigator.msSaveOrOpenBlob) {
// 兼容IE10
navigator.msSaveBlob(blob, filename)
} else {
const href = URL.createObjectURL(blob) // 創(chuàng)建新的URL表示指定的blob對象
const a = document.createElement('a')
a.style.display = 'none'
a.href = href // 指定下載鏈接
a.download = filename // 指定下載文件名
a.click()
URL.revokeObjectURL(a.href) // 釋放URL對象
a.remove();
}
resolve("下載成功!")
})
})
}
let file_num = 0;
const zip = new JSZip();
let zip_obj = [];
let floder_obj = [];
let file_order = 0;
let file_floder = null;
let file_data = [];
let file_title = "";
let cur_title = "";
let breakpoint_num = 500; //斷點數據
let allowZipFile = true; //等待壓縮完成
/**
* [鏈接數組]
* @param {[type]} paths [{"name":"初三排課班級課表","path":""}]
* @return {[type]} 下載壓縮文件 [description]
*/
export const downloadCompressedFiles = ({
paths = [],
title = "文件批量下載",
percentCallback = () => {},
}) => {
allowZipFile = true;
file_order = 0;
cur_title = (title && title) || "文件批量下載";
file_title = paths.length > breakpoint_num ? title ? `${title}文件第1~${breakpoint_num}個` : `文件批量下載文件1~${breakpoint_num}個` : (title && title) || "文件批量下載";
zip_obj[file_order] = new JSZip();
floder_obj[file_order] = zip_obj[file_order].folder(file_title);
// file_floder = zip.folder((title && title) || "文件批量下載");
file_num = 0;
if (paths.length) {
file_data = paths;
if (file_num < paths.length) {
getUrlBlod(paths[file_num].path, paths[file_num].name, percentCallback);
}
}
}
const getUrlBlod = (url, name, percentCallback = () => {}) => {
// 從url獲取文件后綴
let suffix = /\.([0-9a-zA-Z]+)$/i.exec(url)[1];
let promise = httpPost({
url
}).then((data) => {
console.log(file_order, "data123");
// console.log(floder_obj[file_order]);
floder_obj[file_order].file(`${name}.${suffix}`, data, {
binary: true
}); //逐個添加文件
file_num = file_num + 1;
if (file_num != file_data.length) {
if (file_num % breakpoint_num == 0) {
let _temp = file_order;
file_order = file_order + 1;
// file_title = (breakpoint_num + file_num) <= file_data.length ? `${cur_title}文件第${breakpoint_num*_temp}~${file_num}個` : `${cur_title}文件第${file_num}~${file_data.length}個`;
file_title=`${cur_title}文件第${breakpoint_num*_temp}~${file_num}個`;
zip_obj[file_order] = new JSZip();
floder_obj[file_order] = zip_obj[file_order].folder((file_title && file_title) || "文件批量下載");
Notification({
title: '提示',
message: file_title + '開始壓縮文件中!請等待',
type: 'info',
duration: 0
});
allowZipFile = false;
zipGenerateAsync(_temp, percentCallback);
}
percentCallback(file_num)
if (allowZipFile) {
getUrlBlod(file_data[file_num].path, file_data[file_num].name, percentCallback);
}
} else {
if (file_num >= file_data.length) {
file_title = `${cur_title}文件第${breakpoint_num * file_order}~${file_data.length}個`;
}
let _temp = file_order;
Notification({
title: '提示',
message: file_title + '開始壓縮文件中!請等待',
type: 'info',
duration: 0
});
allowZipFile = false;
zipGenerateAsync(_temp, percentCallback);
}
return file_num;
}).catch(err => {
// console.log(err, "err123");
// Message.error(`${name}文件下載失敗!`);
file_num = file_num + 1;
if (file_num != file_data.length) {
if (file_num % breakpoint_num == 0) {
let _temp = file_order;
file_order = file_order + 1;
// file_title = (breakpoint_num + file_num) <= file_data.length ? `${cur_title}文件第${breakpoint_num*_temp}~${file_num}個` : `${cur_title}文件第${file_num}~${file_data.length}個`;
file_title=`${cur_title}文件第${breakpoint_num*_temp}~${file_num}個`;
zip_obj[file_order] = new JSZip();
floder_obj[file_order] = zip_obj[file_order].folder(file_title);
Notification({
title: '提示',
message: file_title + '開始壓縮文件中!請等待',
type: 'info',
duration: 0
});
allowZipFile = false;
zipGenerateAsync(_temp, percentCallback);
}
percentCallback(file_num)
if (allowZipFile) {
getUrlBlod(file_data[file_num].path, file_data[file_num].name, percentCallback);
}
} else {
if (file_num >= file_data.length) {
file_title = `${cur_title}文件第${breakpoint_num * file_order}~${file_data.length}個`;
}
Notification({
title: '提示',
message: file_title + '開始壓縮文件中!請等待',
type: 'info',
duration: 0
});
let _temp = file_order;
allowZipFile = false;
zipGenerateAsync(_temp, percentCallback);
}
});
}
const zipGenerateAsync = (num, percentCallback = () => {}) => {
zip_obj[num].generateAsync({
type: "blob"
}).then((content) => {
Notification({
title: '成功',
message: file_title + '壓縮文件下載成功',
type: 'success',
duration: 0
});
// 生成二進制流
fileSaver.saveAs(
content,
(file_title && `${file_title}.zip`) || "文件批量下載.zip"
); // 利用file-saver保存文件
// Message.error(`壓縮文件下載成功!`);
if (file_num == file_data.length) {
file_num = file_num + 1;
}
percentCallback(file_num);
zip_obj[num] = "";
floder_obj[num] = "";
if (file_num < file_data.length) {
allowZipFile = true;
getUrlBlod(file_data[file_num].path, file_data[file_num].name, percentCallback);
}
// Message({
// message: '壓縮包文件下載成功!',
// type: 'success'
// });
}).catch(err => {
console.log(err, "壓縮下載失敗");
zip_obj[num] = "";
floder_obj[num] = "";
allowZipFile = true;
getUrlBlod(file_data[file_num].path, file_data[file_num].name, percentCallback);
Notification.error({
title: '錯誤',
message: file_title + '壓縮下載失敗',
duration: 0
});
});
}
const getInPath = (url, name = "") => {
return new Promise(async (resolve, reject) => {
// let result = await axiosDownload(url);
// if (result) {
// resolve(result.data);
// } else {
// reject();
// }
await axiosDownload(url).then(res => {
resolve(res.data)
}).catch(err => {
reject(err)
})
});
};
const axiosDownload = (url, resOpts = {}) => {
const {
type = "get", data = ""
} = resOpts;
const queryArgs = {
url,
method: type,
data,
responseType: "blob",
// headers: {//這個地方看情況而定,如果打開會存在跨域問題
// Accept: "application/json",
// "Content-Type": "application/json; charset=utf-8",
// withCredentials: true,
// },
};
// tips: 這里直接返回的是response整體!
return new Promise((resolve, reject) =>
axios
.request(queryArgs)
.then((res) => resolve(res))
.catch((err) => reject(err))
);
};
const axiosConfig = {
// headers: {
// 'Content-Type': 'application/json;charset=UTF-8',
// },
// timeout: 60000,
responseType: 'blob',
}
const request = axios.create(axiosConfig);
let isRefreshing = false;
let queue = [];
let runQueue = () => {
isRefreshing = true
let first = queue.shift();
first.request()
}
//請求攔截
//所有的網絡請求都會先走這個方法
// 添加請求攔截器,所有的網絡請求都會先走這個方法,我們可以在它里面為請求添加一些自定義的內容
request.interceptors.request.use((config) => {
// 在發(fā)送請求之前做些什么
return config;
}, function (error) {
return Promise.reject(error);
});
// 添加響應攔截器
request.interceptors.response.use(function (response) {
isRefreshing = false
if (!(queue.length === 0)) runQueue()
return response.data
}, function (error) {
console.log(error, 2343);
isRefreshing = false
if (!(queue.length === 0)) runQueue()
// 對響應錯誤做點什么
return Promise.reject(error);
});
const httpPost = async ({
url,
method = 'get',
data = "",
}) => {
return new Promise((resolve, reject) => {
queue.push({
request: () => {
request({
method,
url,
data,
}).then(res => {
resolve(res)
}).catch(e => {
reject(e)
})
}
})
if (!isRefreshing) runQueue()
})
}以上就是Java實現文件分片上傳接口的示例代碼的詳細內容,更多關于Java文件分片上傳的資料請關注腳本之家其它相關文章!
您可能感興趣的文章:
相關文章
Java實現拖拽文件上傳dropzone.js的簡單使用示例代碼
本篇文章主要介紹了Java實現拖拽文件上傳dropzone.js的簡單使用示例代碼,具有一定的參考價值,有興趣的可以了解一下2017-07-07
使用@Autowired注解引入server服務層方法時報錯的解決
這篇文章主要介紹了使用@Autowired注解引入server服務層方法時報錯的解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11
springboot中報錯Invalid character found in
這篇文章主要介紹了springboot中報錯Invalid character found in the request的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09
mybatisplus的坑?insert標簽insert?into?select無參數問題的解決
這篇文章主要介紹了mybatisplus的坑?insert標簽insert?into?select無參數問題的解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12
詳解Spring Cloud 斷路器集群監(jiān)控(Turbine)
這篇文章主要介紹了詳解Spring Cloud 斷路器集群監(jiān)控(Turbine),小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-05-05

