| | |
| | | package com.qxueyou.scc.teach.res.service.impl; |
| | | |
| | | |
| | | //import com.example.study.springboot.background.service.HweiYunOBSService; |
| | | //import com.example.study.springboot.config.HweiOBSConfig; |
| | | import com.obs.services.ObsClient; |
| | | import com.obs.services.exception.ObsException; |
| | | import com.obs.services.model.*; |
| | | import com.qxueyou.scc.base.model.FileMeta; |
| | | import com.qxueyou.scc.base.model.Result; |
| | | import com.qxueyou.scc.base.util.CollectionUtils; |
| | | import com.qxueyou.scc.base.util.QFileUtils; |
| | | import com.qxueyou.scc.base.util.UUIDUtils; |
| | | import com.qxueyou.scc.config.HweiOBSConfig; |
| | | import com.qxueyou.scc.teach.res.model.ResFile; |
| | | import com.qxueyou.scc.teach.res.service.HweiYunOBSService; |
| | | import com.qxueyou.scc.teach.res.service.IFileService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.catalina.core.ApplicationPart; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.apache.logging.log4j.LogManager; |
| | | import org.apache.logging.log4j.Logger; |
| | | import org.aspectj.util.FileUtil; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.File; |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | | import java.util.Calendar; |
| | | import java.util.GregorianCalendar; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.*; |
| | | import java.util.concurrent.ExecutorService; |
| | | import java.util.concurrent.Executors; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | /** |
| | | * @ClassName: HweiYunOBSServiceImpl |
| | |
| | | private final Logger log = LogManager.getLogger(HweiYunOBSServiceImpl.class); |
| | | @Autowired |
| | | private HweiOBSConfig hweiOBSConfig; |
| | | |
| | | @Autowired |
| | | FileService fileService; |
| | | |
| | | public final static String FILE_TYPE_VIDEO = "video"; |
| | | |
| | |
| | | "JPG", FILE_TYPE_IMG,"JPEG", FILE_TYPE_IMG, "GIF", FILE_TYPE_IMG, "BMP", FILE_TYPE_IMG, "PNG", FILE_TYPE_IMG |
| | | |
| | | ); |
| | | |
| | | |
| | | @Override |
| | | public boolean delete(String objectKey) { |
| | | ObsClient obsClient = null; |
| | |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public boolean delete(List<String> objectKeys) { |
| | | ObsClient obsClient = null; |
| | |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |
| | | public String fileUpload(MultipartFile uploadFile, String objectKey) { |
| | | public List<FileMeta> fileUpload(MultipartFile uploadFile, String objectKey) { |
| | | ObsClient obsClient = null; |
| | | List<FileMeta> files = new ArrayList<FileMeta>(2); |
| | | FileMeta fileMeta = null; |
| | | try { |
| | | String destPath = getDestPath(objectKey); |
| | | String bucketName = hweiOBSConfig.getBucketName(); |
| | |
| | | } |
| | | InputStream inputStream = uploadFile.getInputStream(); |
| | | long available = inputStream.available(); |
| | | // PutObjectRequest request = new PutObjectRequest(bucketName,objectKey,inputStream); |
| | | PutObjectRequest request = new PutObjectRequest(bucketName,destPath,inputStream); |
| | | ObjectMetadata objectMetadata = new ObjectMetadata(); |
| | | objectMetadata.setContentLength(available); |
| | | request.setMetadata(objectMetadata); |
| | | // request. |
| | | // 设置对象访问权限为公共读 |
| | | request.setAcl(AccessControlList.REST_CANNED_PUBLIC_READ); |
| | | PutObjectResult result = obsClient.putObject(request); |
| | | |
| | | fileMeta = new FileMeta(); |
| | | ResFile file = fileService.insertFileToDBTwo(objectKey, uploadFile.getSize(), result.getObjectUrl(), uploadFile.getContentType()); |
| | | // SetObjectMetadataRequest ObjectMetadataRequest = new SetObjectMetadataRequest(bucketName, destPath); |
| | | // ObjectMetadataRequest.setContentDisposition("inline"); |
| | | // obsClient.setObjectMetadata(ObjectMetadataRequest); |
| | | |
| | | fileMeta.setFileId(file.getFileId()); |
| | | fileMeta.setPath(result.getObjectUrl()); |
| | | fileMeta.setFileSize(uploadFile.getSize() / 1024 + "kb"); |
| | | fileMeta.setFileType(uploadFile.getContentType()); |
| | | fileMeta.setFileName(objectKey); |
| | | files.add(fileMeta); |
| | | // 读取该已上传对象的URL |
| | | log.info("已上传对象的URL" + result.getObjectUrl()); |
| | | return result.getObjectUrl(); |
| | | return files; |
| | | // return result.getObjectUrl(); |
| | | } catch (ObsException e) { |
| | | log.error("obs上传失败", e); |
| | | } catch (IOException e) { |
| | |
| | | return null; |
| | | } |
| | | |
| | | @Override |
| | | public List<FileMeta> fnepian(MultipartFile uploadFile, String objectKey) throws IOException { |
| | | ObsClient obsClient = null; |
| | | List<FileMeta> files = new ArrayList<FileMeta>(2); |
| | | FileMeta fileMeta = null; |
| | | // 每个分片的大小,用于计算文件有多少个分片。单位为字节。 |
| | | final long partSize = 10 * 1024 * 1024L; //10 MB。 |
| | | String bucketName = hweiOBSConfig.getBucketName(); |
| | | obsClient = hweiOBSConfig.getInstance(); |
| | | // objectName 是路径,分片文件最终整合的路径 |
| | | String objectName = "multipartUpload/"+objectKey; |
| | | // 创建InitiateMultipartUploadRequest对象。 |
| | | InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, objectName); |
| | | InitiateMultipartUploadResult prebuilt = obsClient.initiateMultipartUpload(request); |
| | | InputStream inputStream = uploadFile.getInputStream(); |
| | | // 获取全局id |
| | | String uploadId = prebuilt.getUploadId(); |
| | | // 如果并发量大的话 初始化线程池 20线程数量 |
| | | // ExecutorService executorService = Executors.newFixedThreadPool(20); |
| | | // partTags是PartEtag的集合。PartEtag由分片的ETag和分片号组成。 |
| | | List<PartEtag> partTags = new ArrayList<PartEtag>(); |
| | | File file = MultipartFileToFile(uploadFile); |
| | | // 计算有多少个分片 |
| | | int partCount = (int) (file.length() / partSize); |
| | | // 如果取余数不为零则追加一个 |
| | | if (file.length() % partSize != 0) { |
| | | partCount++; |
| | | } |
| | | |
| | | try { |
| | | for (int i = 0; i < partCount; i++) { |
| | | long startPos = i * partSize; |
| | | long curPartSize = (i + 1 == partCount) ? (file.length() - startPos) : partSize; |
| | | // 跳过已经上传的分片。 |
| | | inputStream.skip(startPos); |
| | | UploadPartRequest uploadPartRequest = new UploadPartRequest(); |
| | | uploadPartRequest.setBucketName(bucketName); |
| | | uploadPartRequest.setObjectKey(objectName); |
| | | uploadPartRequest.setUploadId(uploadId); |
| | | uploadPartRequest.setInput(inputStream); |
| | | // 设置分片大小。除了最后一个分片没有大小限制,其他的分片最小为100 KB。 |
| | | uploadPartRequest.setPartSize(curPartSize); |
| | | // 设置分片号。每一个上传的分片都有一个分片号,取值范围是1~10000,如果超出此范围,Obs将返回InvalidArgument错误码。 |
| | | uploadPartRequest.setPartNumber( i + 1); |
| | | // 每个分片不需要按顺序上传,甚至可以在不同客户端上传,obs会按照分片号排序组成完整的文件。 |
| | | UploadPartResult uploadPartResult = obsClient.uploadPart(uploadPartRequest); |
| | | // 每次上传分片之后,ObS的返回结果包含PartETag。PartETag将被保存在partTags中。 |
| | | partTags.add(new PartEtag(uploadPartResult.getEtag(), uploadPartResult.getPartNumber())); |
| | | } |
| | | // 开始线程池时候使用:等待上传完成 |
| | | /* executorService.shutdown(); |
| | | while (!executorService.isTerminated()) |
| | | { |
| | | try |
| | | { |
| | | executorService.awaitTermination(5, TimeUnit.SECONDS); |
| | | } |
| | | catch (InterruptedException e) |
| | | { |
| | | e.printStackTrace(); |
| | | } |
| | | }*/ |
| | | fileMeta = new FileMeta(); |
| | | // 合并分片段 |
| | | // 在执行完成分片上传操作时,需要提供所有有效的partETags。obs收到提交的partETags后,会逐一验证每个分片的有效性。当所有的数据分片验证通过后,obs将把这些分片组合成一个完整的文件。 |
| | | CompleteMultipartUploadRequest multipartUploadRequest = new CompleteMultipartUploadRequest(bucketName, objectName, uploadId, partTags); |
| | | // 完成分片上传。 |
| | | CompleteMultipartUploadResult completeMultipartUploadResult = obsClient.completeMultipartUpload(multipartUploadRequest); |
| | | // 返回全局id,桶名,对象名称 用于后续处理 比如取消分片上传,查询分片信息等 |
| | | fileMeta.setPath(completeMultipartUploadResult.getObjectUrl()); |
| | | fileMeta.setFileSize(uploadFile.getSize() / 1024 + "kb"); |
| | | fileMeta.setFileType(uploadFile.getContentType()); |
| | | fileMeta.setFileName(objectKey); |
| | | files.add(fileMeta); |
| | | return files; |
| | | }catch (Exception e){ |
| | | log.error("分片循环上传失败!"+e.getMessage()); |
| | | return null; |
| | | } |
| | | } |
| | | public static File MultipartFileToFile(MultipartFile multiFile) { |
| | | // 获取文件名 |
| | | String fileName = multiFile.getOriginalFilename(); |
| | | // 获取文件后缀 |
| | | String prefix = fileName.substring(fileName.lastIndexOf(".")); |
| | | // 若须要防止生成的临时文件重复,能够在文件名后添加随机码 |
| | | |
| | | try { |
| | | File file = File.createTempFile(getFileNameNotPrefix(fileName), prefix); |
| | | multiFile.transferTo(file); |
| | | return file; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | return null; |
| | | } |
| | | /** |
| | | * 获取文件名不带后缀 |
| | | * |
| | | * @param fileName |
| | | * @return |
| | | */ |
| | | public static String getFileNameNotPrefix(String fileName) { |
| | | String prefix = fileName.substring(fileName.indexOf(".")); |
| | | int num = prefix.length();//得到后缀名长度 |
| | | String fileOtherName = fileName.substring(0, fileName.length() - num);//得到文件名。去掉了后缀 |
| | | return fileOtherName; |
| | | } |
| | | |
| | | private String getDestPath(String name) { |
| | | String fileType = getFileType(name); |
| | | |
| | | StringBuffer path = new StringBuffer(128); |
| | | path.append(fileType); |
| | | // path.append(fileType); |
| | | |
| | | Calendar now = new GregorianCalendar(); |
| | | |
| | | path.append('/'); |
| | | path.append(now.get(Calendar.YEAR)); |
| | | path.append(StringUtils.leftPad(String.valueOf(now.get(Calendar.MONTH)), 2, '0')); |
| | | path.append('/'); |
| | | path.append(now.get(Calendar.DAY_OF_MONTH)); |
| | | path.append('/'); |
| | | // path.append('/'); |
| | | // path.append(now.get(Calendar.YEAR)); |
| | | // path.append(StringUtils.leftPad(String.valueOf(now.get(Calendar.MONTH)), 2, '0')); |
| | | // path.append('/'); |
| | | // path.append(now.get(Calendar.DAY_OF_MONTH)); |
| | | // path.append('/'); |
| | | path.append(UUIDUtils.UUID()); |
| | | path.append('.'); |
| | | path.append(QFileUtils.getFileFormat(name)); |
| | |
| | | } |
| | | return null; |
| | | } |
| | | } |
| | | } |