<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
檔案上傳工具--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不以檔案分隔符(/或)結尾時,自動新增檔案分隔符,不同系統下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++) { // 迴圈刪除所有的子檔案及子資料夾 // 刪除子檔案 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"); //建立不同的資料夾目錄 File file = new File(_pathStr); //判斷資料夾是否存在 if (!file.exists()) { //如果資料夾不存在,則建立新的的資料夾 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) // 建立新的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) => { // 在傳送請求之前做些什麼 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檔案分片上傳的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45