阿里云文件上传工具类
生活随笔
收集整理的這篇文章主要介紹了
阿里云文件上传工具类
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
文件實體類
@Data public class UploadFile {private String fileName;private String fileType;private long fileSize;private String timeStampName;private int success;private String message;private String url;private Integer storageType;//切片上傳相關參數(shù)private String taskId;private int chunkNumber;private long chunkSize;private int totalChunks;private String identifier;private long totalSize;private long currentChunkSize;}文件上傳工具父類:
@Slf4j public abstract class Uploader {public static final String ROOT_PATH = "upload";public static final String FILE_SEPARATOR = "/";// 文件大小限制,單位KBpublic final int maxSize = 10000000;public abstract List<UploadFile> upload(HttpServletRequest request, UploadFile uploadFile);public abstract void cancelUpload(UploadFile uploadFile);/*** 獲取本地文件保存路徑** @return*/protected String getLocalFileSavePath() {String path = ROOT_PATH;SimpleDateFormat formater = new SimpleDateFormat("yyyyMMdd");path = FILE_SEPARATOR + path + FILE_SEPARATOR + formater.format(new Date());String staticPath = PathUtil.getStaticPath();File dir = new File(staticPath + path);//LOG.error(PathUtil.getStaticPath() + path);if (!dir.exists()) {try {boolean isSuccessMakeDir = dir.mkdirs();if (!isSuccessMakeDir) {log.error("目錄創(chuàng)建失敗:" + PathUtil.getStaticPath() + path);}} catch (Exception e) {log.error("目錄創(chuàng)建失敗" + PathUtil.getStaticPath() + path);return "";}}return path;}/*** 依據(jù)原始文件名生成新文件名** @return*/protected String getTimeStampName() {try {SecureRandom number = SecureRandom.getInstance("SHA1PRNG");return "" + number.nextInt(10000)+ System.currentTimeMillis();} catch (NoSuchAlgorithmException e) {log.error("生成安全隨機數(shù)失敗");}return ""+ System.currentTimeMillis();}public synchronized boolean checkUploadStatus(UploadFile param, File confFile) throws IOException {RandomAccessFile confAccessFile = new RandomAccessFile(confFile, "rw");//設置文件長度confAccessFile.setLength(param.getTotalChunks());//設置起始偏移量confAccessFile.seek(param.getChunkNumber() - 1);//將指定的一個字節(jié)寫入文件中 127,confAccessFile.write(Byte.MAX_VALUE);byte[] completeStatusList = FileUtils.readFileToByteArray(confFile);confAccessFile.close();//不關閉會造成無法占用//創(chuàng)建conf文件文件長度為總分片數(shù),每上傳一個分塊即向conf文件中寫入一個127,那么沒上傳的位置就是默認的0,已上傳的就是127for (int i = 0; i < completeStatusList.length; i++) {if (completeStatusList[i] != Byte.MAX_VALUE) {return false;}}confFile.delete();return true;}protected String getFileName(String fileName){if (!fileName.contains(".")) {return fileName;}return fileName.substring(0, fileName.lastIndexOf("."));} }阿里云文件上傳子類:
package com.qiwenshare.ufo.operation.upload.product;import com.alibaba.fastjson.JSON; import com.aliyun.oss.OSS; import com.aliyun.oss.OSSClientBuilder; import com.aliyun.oss.model.*; import com.qiwenshare.common.util.FileUtil; import com.qiwenshare.ufo.autoconfiguration.UFOAutoConfiguration; import com.qiwenshare.ufo.autoconfiguration.UFOProperties; import com.qiwenshare.ufo.exception.UploadException; import com.qiwenshare.ufo.operation.upload.Uploader; import com.qiwenshare.ufo.operation.upload.domain.UploadFile; import com.qiwenshare.ufo.util.PathUtil; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest;import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import java.io.File; import java.util.*;@Slf4j @Component public class AliyunOSSUploader extends Uploader {// partETags是PartETag的集合。PartETag由分片的ETag和分片號組成。public static Map<String, List<PartETag>> partETagsMap = new HashMap<String, List<PartETag>>();public static Map<String, UploadFileInfo> uploadPartRequestMap = new HashMap<>();public static Map<String, OSS> ossMap = new HashMap<>();@Overridepublic List<UploadFile> upload(HttpServletRequest httpServletRequest, UploadFile uploadFile) {log.info("開始上傳upload");List<UploadFile> saveUploadFileList = new ArrayList<>();StandardMultipartHttpServletRequest request = (StandardMultipartHttpServletRequest) httpServletRequest;boolean isMultipart = ServletFileUpload.isMultipartContent(request);if (!isMultipart) {throw new UploadException("未包含文件上傳域");}Iterator<String> iter = request.getFileNames();while (iter.hasNext()) {saveUploadFileList = doUpload(request, iter, uploadFile);}log.info("結(jié)束上傳");return saveUploadFileList;}private List<UploadFile> doUpload(StandardMultipartHttpServletRequest standardMultipartHttpServletRequest, Iterator<String> iter, UploadFile uploadFile) {String savePath = getLocalFileSavePath();OSS ossClient = getClient(uploadFile);List<UploadFile> saveUploadFileList = new ArrayList<>();try {MultipartFile multipartfile = standardMultipartHttpServletRequest.getFile(iter.next());String timeStampName = getTimeStampName();String originalName = multipartfile.getOriginalFilename();String fileName = getFileName(originalName);String fileType = FileUtil.getFileExtendName(originalName);uploadFile.setFileName(fileName);uploadFile.setFileType(fileType);uploadFile.setTimeStampName(timeStampName);String ossFilePath = savePath + FILE_SEPARATOR + timeStampName + FILE_SEPARATOR + fileName + "." + fileType;String confFilePath = savePath + FILE_SEPARATOR + uploadFile.getIdentifier() + "." + "conf";File confFile = new File(PathUtil.getStaticPath() + FILE_SEPARATOR + confFilePath);synchronized (AliyunOSSUploader.class) {if (uploadPartRequestMap.get(uploadFile.getIdentifier()) == null) {InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(UFOAutoConfiguration.aliyunConfig.getOss().getBucketName(), ossFilePath.substring(1));InitiateMultipartUploadResult upresult = ossClient.initiateMultipartUpload(request);String uploadId = upresult.getUploadId();UploadFileInfo uploadPartRequest = new UploadFileInfo();uploadPartRequest.setBucketName(UFOAutoConfiguration.aliyunConfig.getOss().getBucketName());uploadPartRequest.setKey(ossFilePath.substring(1));uploadPartRequest.setUploadId(uploadId);uploadPartRequestMap.put(uploadFile.getIdentifier(), uploadPartRequest);}}UploadFileInfo uploadFileInfo = uploadPartRequestMap.get(uploadFile.getIdentifier());UploadPartRequest uploadPartRequest = new UploadPartRequest();uploadPartRequest.setBucketName(uploadFileInfo.getBucketName());uploadPartRequest.setKey(uploadFileInfo.getKey());uploadPartRequest.setUploadId(uploadFileInfo.getUploadId());uploadPartRequest.setInputStream(multipartfile.getInputStream());uploadPartRequest.setPartSize(uploadFile.getCurrentChunkSize());uploadPartRequest.setPartNumber(uploadFile.getChunkNumber());log.info(JSON.toJSONString(uploadPartRequest));UploadPartResult uploadPartResult = ossClient.uploadPart(uploadPartRequest);synchronized (AliyunOSSUploader.class) {log.info("上傳結(jié)果:" + JSON.toJSONString(uploadPartResult));if (partETagsMap.get(uploadFile.getIdentifier()) == null) {List<PartETag> partETags = new ArrayList<PartETag>();partETags.add(uploadPartResult.getPartETag());partETagsMap.put(uploadFile.getIdentifier(), partETags);} else {partETagsMap.get(uploadFile.getIdentifier()).add(uploadPartResult.getPartETag());}}boolean isComplete = checkUploadStatus(uploadFile, confFile);if (isComplete) {log.info("分片上傳完成");completeMultipartUpload(uploadFile);uploadFile.setUrl("/" + uploadPartRequestMap.get(uploadFile.getIdentifier()).getKey());uploadFile.setSuccess(1);uploadFile.setMessage("上傳成功");partETagsMap.remove(uploadFile.getIdentifier());uploadPartRequestMap.remove(uploadFile.getIdentifier());ossMap.remove(uploadFile.getIdentifier());} else {uploadFile.setSuccess(0);uploadFile.setMessage("未完成");}} catch (Exception e) {log.error("上傳出錯:" + e);throw new UploadException(e);}uploadFile.setStorageType(1);uploadFile.setFileSize(uploadFile.getTotalSize());saveUploadFileList.add(uploadFile);return saveUploadFileList;}/*** 將文件分塊進行升序排序并執(zhí)行文件上傳。*/protected void completeMultipartUpload(UploadFile uploadFile) {List<PartETag> partETags = partETagsMap.get(uploadFile.getIdentifier());Collections.sort(partETags, Comparator.comparingInt(PartETag::getPartNumber));UploadFileInfo uploadFileInfo = uploadPartRequestMap.get(uploadFile.getIdentifier());CompleteMultipartUploadRequest completeMultipartUploadRequest =new CompleteMultipartUploadRequest(UFOAutoConfiguration.aliyunConfig.getOss().getBucketName(),uploadFileInfo.getKey(),uploadFileInfo.getUploadId(),partETags);log.info("----:" + JSON.toJSONString(partETags));// 完成上傳。CompleteMultipartUploadResult completeMultipartUploadResult = getClient(uploadFile).completeMultipartUpload(completeMultipartUploadRequest);log.info("----:" + JSON.toJSONString(completeMultipartUploadRequest));getClient(uploadFile).shutdown();//}private void listFile(UploadFile uploadFile) {// 列舉已上傳的分片,其中uploadId來自于InitiateMultipartUpload返回的結(jié)果。ListPartsRequest listPartsRequest = new ListPartsRequest(UFOAutoConfiguration.aliyunConfig.getOss().getBucketName(), uploadPartRequestMap.get(uploadFile.getIdentifier()).getKey(), uploadPartRequestMap.get(uploadFile.getIdentifier()).getUploadId());// 設置uploadId。//listPartsRequest.setUploadId(uploadId);// 設置分頁時每一頁中分片數(shù)量為100個。默認列舉1000個分片。listPartsRequest.setMaxParts(100);// 指定List的起始位置。只有分片號大于此參數(shù)值的分片會被列舉。 // listPartsRequest.setPartNumberMarker(1);PartListing partListing = getClient(uploadFile).listParts(listPartsRequest);for (PartSummary part : partListing.getParts()) {log.info("分片號:"+part.getPartNumber() + ", 分片數(shù)據(jù)大小: "+part.getSize() + ",分片的ETag:"+part.getETag()+ ", 分片最后修改時間:"+ part.getLastModified());// 獲取分片號。part.getPartNumber();// 獲取分片數(shù)據(jù)大小。part.getSize();// 獲取分片的ETag。part.getETag();// 獲取分片的最后修改時間。part.getLastModified();}}/*** 取消上傳*/@Overridepublic void cancelUpload(UploadFile uploadFile) {AbortMultipartUploadRequest abortMultipartUploadRequest =new AbortMultipartUploadRequest(UFOAutoConfiguration.aliyunConfig.getOss().getBucketName(), uploadPartRequestMap.get(uploadFile.getIdentifier()).getKey(), uploadPartRequestMap.get(uploadFile.getIdentifier()).getUploadId());getClient(uploadFile).abortMultipartUpload(abortMultipartUploadRequest);}private synchronized OSS getClient(UploadFile uploadFile) {OSS ossClient = null;if (ossMap.get(uploadFile.getIdentifier()) == null) {ossClient = new OSSClientBuilder().build(UFOAutoConfiguration.aliyunConfig.getOss().getEndpoint(), UFOAutoConfiguration.aliyunConfig.getOss().getAccessKeyId(), UFOAutoConfiguration.aliyunConfig.getOss().getAccessKeySecret());ossMap.put(uploadFile.getIdentifier(), ossClient);} else {ossClient = ossMap.get(uploadFile.getIdentifier());}return ossClient;}@Datapublic class UploadFileInfo {private String bucketName;private String key;private String uploadId;}}路徑工具類
import com.qiwenshare.common.constant.FileConstant; import com.qiwenshare.ufo.autoconfiguration.UFOAutoConfiguration; import org.apache.commons.lang3.StringUtils; import org.springframework.util.ResourceUtils;import java.io.File; import java.io.FileNotFoundException; import java.io.UnsupportedEncodingException; import java.net.URLDecoder;public class PathUtil {/*** 獲取項目所在的根目錄路徑 resources路徑* @return*/public static String getProjectRootPath() {String absolutePath = null;try {String url = ResourceUtils.getURL("classpath:").getPath();absolutePath = urlDecode(new File(url).getAbsolutePath()) + File.separator;} catch (FileNotFoundException e) {e.printStackTrace();}return absolutePath;}/*** 路徑解碼* @param url* @return*/public static String urlDecode(String url){String decodeUrl = null;try {decodeUrl = URLDecoder.decode(url, "utf-8");} catch (UnsupportedEncodingException e) {e.printStackTrace();}return decodeUrl;}/*** 得到static路徑** @return*/public static String getStaticPath() {String localStoragePath = UFOAutoConfiguration.localStoragePath;//PropertiesUtil.getProperty("qiwen-file.local-storage-path")if (StringUtils.isNotEmpty(localStoragePath)) {return localStoragePath;}else {String projectRootAbsolutePath = getProjectRootPath();int index = projectRootAbsolutePath.indexOf("file:");if (index != -1) {projectRootAbsolutePath = projectRootAbsolutePath.substring(0, index);}return projectRootAbsolutePath + "static" + File.separator;}}public static String getParentPath(String path) {return path.substring(0, path.lastIndexOf(FileConstant.pathSeparator));}}總結(jié)
以上是生活随笔為你收集整理的阿里云文件上传工具类的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 对二维数组自定义排序、Treemap自定
- 下一篇: proto的介绍和基础使用