当前位置: 首页 > news >正文

做网站哪些技术免费开放的api大全软件

做网站哪些技术,免费开放的api大全软件,纯静态网站页面优化,提升学历图片素材文章目录 一、流程设计1. 分片上传实现思路2. 文件分片上传流程3. 视频播放流程 二、代码实现1. 后端代码2. 文件上传前端代码3. 视频播放前端代码 一、流程设计 1. 分片上传实现思路 2. 文件分片上传流程 3. 视频播放流程 二、代码实现 1. 后端代码 pom.xml dependenc… 文章目录 一、流程设计1. 分片上传实现思路2. 文件分片上传流程3. 视频播放流程 二、代码实现1. 后端代码2. 文件上传前端代码3. 视频播放前端代码 一、流程设计 1. 分片上传实现思路 2. 文件分片上传流程 3. 视频播放流程 二、代码实现 1. 后端代码 pom.xml dependencygroupIdio.minio/groupIdartifactIdminio/artifactIdversion8.5.5/version /dependencyapplication.yml spring:servlet:multipart:max-file-size: 300MBmax-request-size: 300MBminio:endpoint: http://127.0.0.1:9000 #MinIO服务所在地址accessKey: admin #访问的keysecretKey: password #访问的秘钥bucketName: test #访问的存储桶名expiry: 86400 #过期时间com.example.web.dto.file.FileResp package com.example.web.dto.file;import com.example.web.dto.CommResp; import java.io.Serializable;/*** description 文件处理返回消息*/ lombok.Setter lombok.Getter public class FileResp extends CommResp implements Serializable {private static final long serialVersionUID 1L;// 文件处理代码private Integer code;// 文件名private String fileName;// 文件数量private Integer shardCount;// 文件MD5private String md5;// 文件访问路径private String fileUrl;public void setResp() {if (getCode()!null getCode()200) setMsg(操作成功);if (getCode()!null getCode()201) setMsg(分片上传成功);if (getCode()!null getCode()202) setMsg(所有的分片均上传成功);if (getCode()!null getCode()203) setMsg(系统异常);if (getCode()!null getCode()204) setMsg(资源不存在);setPageNo(null);setPageSize(null);setTotals(null);}}com.example.web.dto.file.MinioObject package com.example.web.dto.file;import java.io.Serializable; import java.util.Map;lombok.Setter lombok.Getter public class MinioObject implements Serializable {private static final long serialVersionUID 1L;private String bucket;private String region;private String object;private String etag;private long size;private boolean deleteMarker;private MapString, String userMetadata;}com.example.utils.FileMd5Util package com.example.utils;import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.security.DigestInputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException;/*** description 计算文件的Md5*/ public final class FileMd5Util {private static final int BUFFER_SIZE 8 * 1024;private static final char[] HEX_CHARS {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f};/*** 计算文件的输入流*/public static String calculateMd5(InputStream inputStream) {try {MessageDigest md5MessageDigest MessageDigest.getInstance(MD5);try (BufferedInputStream bis new BufferedInputStream(inputStream);DigestInputStream digestInputStream new DigestInputStream(bis, md5MessageDigest)) {final byte[] buffer new byte[BUFFER_SIZE];while (digestInputStream.read(buffer) 0) {md5MessageDigest digestInputStream.getMessageDigest();}return encodeHex(md5MessageDigest.digest());} catch (IOException ioException) {throw new IllegalArgumentException(ioException.getMessage());}} catch (NoSuchAlgorithmException e) {throw new IllegalArgumentException(no md5 found);}}/*** 转成的md5值为全小写*/private static String encodeHex(byte[] bytes) {char[] chars new char[32];for (int i 0; i chars.length; i i 2) {byte b bytes[i / 2];chars[i] HEX_CHARS[(b 0x4) 0xf];chars[i 1] HEX_CHARS[b 0xf];}return new String(chars);} }com.example.utils.MinioFileUtil package com.example.utils;import io.minio.*; import io.minio.http.Method; import io.minio.messages.DeleteError; import io.minio.messages.DeleteObject; import io.minio.messages.Item; import lombok.SneakyThrows; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.util.ObjectUtils; import java.io.*; import java.util.ArrayList; import java.util.List;/*** description minio文件操作*/ lombok.Getter Component public class MinioFileUtil {private static Log logger LogFactory.getLog(MinioFileUtil.class);Value(${minio.endpoint:1})private String minioEndpoint;Value(${minio.accessKey:1})private String minioAccessKey;Value(${minio.secretKey:1})private String minioSecretKey;Value(${minio.file-show-url:1})private String showUrl;/*** description 获取minioClient*/public MinioClient getMinioClient() {return MinioClient.builder().endpoint(minioEndpoint).credentials(minioAccessKey, minioSecretKey).build();}/*** description 将分钟数转换为秒数* Param expiry 过期时间分钟*/private int expiryHandle(Integer expiry) {expiry expiry * 60;if (expiry 604800) {return 604800;}return expiry;}/*** description 文件上传至指定桶容器并返回对象文件的存储路径加文件名* param inputStream 文件流* param bucketName 桶名称* param directory 文件存储目录* param objectName 文件名称*/SneakyThrowspublic String uploadObject(InputStream inputStream, String bucketName, String directory, String objectName) {if (StringUtils.isNotEmpty(directory)) {objectName directory / objectName;}getMinioClient().putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(inputStream, inputStream.available(), -1).build());return objectName;}/*** description 获取访问对象的url地址* param bucketName 桶名称* param objectName 文件名称(包含存储目录)* param expiry 过期时间(分钟) 最大为7天 超过7天则默认最大值*/SneakyThrowspublic String getObjectUrl(String bucketName, String objectName, Integer expiry) {expiry expiryHandle(expiry);String url getMinioClient().getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(bucketName).object(objectName).expiry(expiry).build());if (!showUrl.equals(1) showUrl.length()2) {url url.replace(minioEndpoint, showUrl);}return url;}/*** description 获取某个文件* param bucketName 桶名称* param objectName 文件路径*/SneakyThrowspublic StatObjectResponse getObjectInfo(String bucketName, String objectName) {return getMinioClient().statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());}/*** description 删除一个对象文件* param bucketName 桶名称* param objectName 文件名称(包含存储目录)*/public boolean removeObject(String bucketName, String objectName) {try {getMinioClient().removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build());return true;} catch (Exception e) {logger.error(removeObject error, e);return false;}}/*** description 删除多个对象文件* param bucketName 桶名称* param objectNames 文件名称(包含存储目录)*/SneakyThrowspublic ListString removeObjects(String bucketName, ListString objectNames) {if (!bucketExists(bucketName)) {return new ArrayList();}ListString deleteErrorNames new ArrayList();ListDeleteObject deleteObjects new ArrayList(objectNames.size());for (String objectName : objectNames) {deleteObjects.add(new DeleteObject(objectName));}IterableResultDeleteError results getMinioClient().removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(deleteObjects).build());for (ResultDeleteError result : results) {DeleteError error result.get();deleteErrorNames.add(error.objectName());}return deleteErrorNames;}/*** description 判断bucket是否存在* param bucketName 桶名称*/SneakyThrowspublic boolean bucketExists(String bucketName) {boolean exists false;BucketExistsArgs.Builder builder BucketExistsArgs.builder();BucketExistsArgs build builder.bucket(bucketName).build();exists getMinioClient().bucketExists(build);return exists;}/*** description 创建存储桶* minio 桶设置公共或私有alioss统一设置成私有可配置文件公共读或私有读* param bucketName 桶名称*/SneakyThrowspublic void makeBucket(String bucketName) {if (bucketExists(bucketName)) {return;}getMinioClient().makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());}/*** description 获取文件* param bucketName 桶名称* param objectName 文件路径* param offset 截取流的开始位置* param length 截取长度*/SneakyThrowspublic InputStream getObject(String bucketName, String objectName, Long offset, Long length) {return getMinioClient().getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).offset(offset).length(length).build());}/*** description 获取文件* param bucketName 桶名称* param objectName 文件路径*/SneakyThrowspublic InputStream getObject(String bucketName, String objectName) {return getMinioClient().getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());}/*** description 上传分片文件* param inputStream 输入流* param objectName 文件路径* param bucketName 桶名称*/SneakyThrowspublic void putChunkObject(InputStream inputStream, String bucketName, String objectName) {try {getMinioClient().putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(inputStream, inputStream.available(), -1).build());} finally {if (inputStream ! null) {inputStream.close();}}}/*** description 删除空桶* param bucketName 桶名称*/SneakyThrowspublic void removeBucket(String bucketName) {removeObjects(bucketName, listObjectNames(bucketName));getMinioClient().removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());}/*** description 查询桶中所有的文件* param bucketName 桶名称*/SneakyThrowspublic ListString listObjectNames(String bucketName) {ListString objectNameList new ArrayList();if (bucketExists(bucketName)) {IterableResultItem objects getMinioClient().listObjects(ListObjectsArgs.builder().bucket(bucketName).recursive(true).build());for (ResultItem result : objects) {Item item result.get();objectNameList.add(item.objectName());}}return objectNameList;}/*** description 文件合并* param originBucketName 分块文件所在的桶* param targetBucketName 合并文件生成文件所在的桶* param objectName 存储于桶中的对象名*/SneakyThrowspublic String composeObject(String originBucketName, String targetBucketName, String objectName) {IterableResultItem results getMinioClient().listObjects(ListObjectsArgs.builder().bucket(originBucketName).recursive(true).build());ListString objectNameList new ArrayList();for (ResultItem result : results) {Item item result.get();objectNameList.add(item.objectName());}if (ObjectUtils.isEmpty(objectNameList)) {throw new IllegalArgumentException(originBucketName 桶中没有文件请检查);}ListComposeSource composeSourceList new ArrayList(objectNameList.size());// 对文件名集合进行升序排序objectNameList.sort((o1, o2) - Integer.parseInt(o2) Integer.parseInt(o1) ? -1 : 1);for (String object : objectNameList) {composeSourceList.add(ComposeSource.builder().bucket(originBucketName).object(object).build());}return composeObject(composeSourceList, targetBucketName, objectName);}/*** description 文件合并* param bucketName 合并文件生成文件所在的桶* param objectName 原始文件名* param sourceObjectList 分块文件集合*/SneakyThrowspublic String composeObject(ListComposeSource sourceObjectList, String bucketName, String objectName) {getMinioClient().composeObject(ComposeObjectArgs.builder().bucket(bucketName).object(objectName).sources(sourceObjectList).build());return getObjectUrl(bucketName, objectName, 100);} }com.example.blh.file.FileBlh package com.example.blh.file;import com.alibaba.fastjson2.JSONObject; import com.example.entity.CommBo; import com.example.entity.file.FileBo; import com.example.utils.FileMd5Util; import com.example.utils.MinioFileUtil; import com.example.web.dto.file.MinioObject; import com.fasterxml.jackson.databind.ObjectMapper; import io.minio.StatObjectResponse; import org.apache.catalina.connector.ClientAbortException; import org.apache.commons.compress.utils.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartHttpServletRequest; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.util.*;/*** description 文件上传下载处理逻辑*/ Component public class FileBlh {private static Log logger LogFactory.getLog(FileBlh.class);private static final String OBJECT_INFO_LIST minio.file.objects;private static final String MD5_KEY minio.file.md5s;private static final SimpleDateFormat dateFormat new SimpleDateFormat(yyyyMM);Value(${minio-bucket-name:1})private String bucketName;Resourceprivate MinioFileUtil minioFileUtil;Resourceprivate RedisTemplate redisTemplate;Autowiredprivate ObjectMapper objectMapper;/*** description 上传单个文件*/public void uploadFile(FileBo bo) {InputStream is null;try {MultipartHttpServletRequest multipartRequest (MultipartHttpServletRequest) bo.getReq();MultipartFile file multipartRequest.getFile(file);is file.getInputStream();String uuid UUID.randomUUID().toString().replace(-,);String dir dateFormat.format(new Date());minioFileUtil.uploadObject(is,bucketName,dir,uuid-file.getOriginalFilename());bo.setFileName(dir/uuid-file.getOriginalFilename());CommBo.setSuccessBo(bo);} catch (Exception e) {CommBo.setFailBo(bo, e);} finally {try {if (is!null) is.close();} catch (IOException eis) {}}}/*** description 获取文件路径*/public void getFileUrl(FileBo bo) {try {bo.setFileUrl(minioFileUtil.getObjectUrl(bucketName,bo.getFileName(),100));CommBo.setSuccessBo(bo);} catch (Exception e) {CommBo.setFailBo(bo, e);}}/*** description 删除文件*/public void deleteFile(FileBo bo) {try {minioFileUtil.removeObject(bucketName,bo.getFileName());CommBo.setSuccessBo(bo);} catch (Exception e) {CommBo.setFailBo(bo, e);}}/*** description 获取文件分片下载信息*/public void getSplitFileInfo(FileBo bo) {try {StatObjectResponse objectInfo minioFileUtil.getObjectInfo(bucketName,bo.getFileName());bo.setShardCount((int)Math.ceil((double)objectInfo.size()/(1024*1024*5)));CommBo.setSuccessBo(bo);} catch (Exception e) {CommBo.setFailBo(bo, e);}}/*** description 文件分片下载*/public void downSplitFile(FileBo bo) {try {StatObjectResponse objectInfo minioFileUtil.getObjectInfo(bucketName,bo.getFileName());long fileSize objectInfo.size();long startPos (bo.getShardCount()-1) * (1024*1024*5);long endPos bo.getShardCount() * (1024*1024*5);if (endPosfileSize) {endPos fileSize;}long rangLength endPos - startPos;bo.getRes().addHeader(Content-Type, */*);BufferedOutputStream bos new BufferedOutputStream(bo.getRes().getOutputStream());BufferedInputStream bis new BufferedInputStream(minioFileUtil.getObject(bucketName, bo.getFileName(), startPos, rangLength));IOUtils.copy(bis, bos);} catch (Exception e) {CommBo.setFailBo(bo, e);}}/*** description 根据文件大小和文件的md5校验文件是否存在*/public void checkSplitFile(FileBo bo) {try {if (ObjectUtils.isEmpty(bo.getMd5())) {bo.setCode(204);return;}String url (String) redisTemplate.boundHashOps(MD5_KEY).get(bo.getMd5());if (ObjectUtils.isEmpty(url)) {bo.setCode(204); // 文件不存在return;}bo.setCode(200);bo.setFileUrl(url);} catch (Exception e) {CommBo.setFailBo(bo, e);}}/*** description 文件上传适合大文件集成了分片上传*/public void uploadSplitFile(FileBo bo) {try {MultipartHttpServletRequest multipartRequest (MultipartHttpServletRequest) bo.getReq();MultipartFile file multipartRequest.getFile(data);if (file null) {bo.setCode(203);return;}int index Integer.parseInt(multipartRequest.getParameter(index)); // 第几片int total Integer.parseInt(multipartRequest.getParameter(total)); // 总片数String fileName multipartRequest.getParameter(name);String md5 multipartRequest.getParameter(md5);minioFileUtil.makeBucket(md5);String objectName String.valueOf(index);if (index total) {try {logger.info(上传文件: md5 objectName);minioFileUtil.putChunkObject(file.getInputStream(), md5, objectName); // 上传文件bo.setCode(201); // 不是最后一片, 状态码为201} catch (Exception e) {logger.error(e.getMessage());bo.setCode(203);}} else {try {minioFileUtil.putChunkObject(file.getInputStream(), md5, objectName);bo.setCode(202); // 最后一片, 状态码为202bo.setFileName(objectName);} catch (Exception e) {logger.error(e.getMessage());bo.setCode(203);}}} catch (Exception e) {CommBo.setFailBo(bo, e);}}/*** description 文件合并*/public void mergeSplitFile(FileBo bo) {logger.info(分片总数: bo.getShardCount());MapString, Object retMap new HashMap();try {ListString objectNameList minioFileUtil.listObjectNames(bo.getMd5());if (bo.getShardCount() ! objectNameList.size()) {bo.setCode(203);} else {// 开始合并请求String filenameExtension StringUtils.getFilenameExtension(bo.getFileName());String uuid UUID.randomUUID().toString();String dir dateFormat.format(new Date());String objectName dir/uuid-bo.getFileName();minioFileUtil.composeObject(bo.getMd5(), bucketName, objectName);// 合并成功之后删除对应的临时桶minioFileUtil.removeBucket(bo.getMd5());logger.info(创建文件 objectName ,删除桶 bo.getMd5() 成功);// 计算文件的md5String fileMd5 null;try (InputStream inputStream minioFileUtil.getObject(bucketName, objectName)) {fileMd5 FileMd5Util.calculateMd5(inputStream);} catch (IOException e) {logger.error(e.getMessage());}// 计算文件真实的类型String type null;if (!ObjectUtils.isEmpty(fileMd5) fileMd5.equalsIgnoreCase(bo.getMd5())) {String url minioFileUtil.getObjectUrl(bucketName, objectName, 100);redisTemplate.boundHashOps(MD5_KEY).put(fileMd5, objectName);bo.setCode(200);} else {minioFileUtil.removeObject(bucketName, objectName);redisTemplate.boundHashOps(MD5_KEY).delete(fileMd5);bo.setCode(203);}bo.setFileName(objectName);}} catch (Exception e) {logger.error(e.getMessage(), e);bo.setCode(203);}}/*** description 文件播放*/public void videoPlay(FileBo bo) {logger.info(播放视频: bo.getFileName());// 设置响应报头String key bucketName . bo.getFileName();Object obj redisTemplate.boundHashOps(OBJECT_INFO_LIST).get(key);// 记录视频文件的元数据MinioObject minioObject;if (obj null) {StatObjectResponse objectInfo null;try {objectInfo minioFileUtil.getObjectInfo(bucketName,bo.getFileName());} catch (Exception e) {bo.getRes().setCharacterEncoding(StandardCharsets.UTF_8.toString());bo.getRes().setContentType(application/json;charsetutf-8);bo.getRes().setStatus(HttpServletResponse.SC_NOT_FOUND);try {JSONObject json new JSONObject();json.put(operateSuccess,false);bo.getRes().getWriter().write(objectMapper.writeValueAsString(json));} catch (IOException ex) {throw new RuntimeException(ex);}return;}minioObject new MinioObject();BeanUtils.copyProperties(objectInfo, minioObject);redisTemplate.boundHashOps(OBJECT_INFO_LIST).put(key, minioObject);} else {minioObject (MinioObject) obj;}// 获取文件的长度long fileSize minioObject.getSize();// Accept-Ranges: bytesbo.getRes().setHeader(Accept-Ranges, bytes);// pos开始读取位置; last最后读取位置long startPos 0;long endPos fileSize - 1;String rangeHeader bo.getReq().getHeader(Range);if (!ObjectUtils.isEmpty(rangeHeader) rangeHeader.startsWith(bytes)) {try {String numRang bo.getReq().getHeader(Range).replaceAll(bytes, );if (numRang.startsWith(-)) {endPos fileSize - 1;startPos endPos - Long.parseLong(new String(numRang.getBytes(StandardCharsets.UTF_8), 1,numRang.length() - 1)) 1;} else if (numRang.endsWith(-)) {endPos fileSize - 1;startPos Long.parseLong(new String(numRang.getBytes(StandardCharsets.UTF_8), 0,numRang.length() - 1));} else {String[] strRange numRang.split(-);if (strRange.length 2) {startPos Long.parseLong(strRange[0].trim());endPos Long.parseLong(strRange[1].trim());} else {startPos Long.parseLong(numRang.replaceAll(-, ).trim());}}if (startPos 0 || endPos 0 || endPos fileSize || startPos endPos) {// 要求的范围不满足bo.getRes().setStatus(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);return;}// 断点续传 状态码206bo.getRes().setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);} catch (NumberFormatException e) {logger.error(e.getMessage());startPos 0;}}// 总共需要读取的字节long rangLength endPos - startPos 1;bo.getRes().setHeader(Content-Range, String.format(bytes %d-%d/%d, startPos, endPos, fileSize));bo.getRes().addHeader(Content-Length, String.valueOf(rangLength));bo.getRes().addHeader(Content-Type, video/mp4);try (BufferedOutputStream bos new BufferedOutputStream(bo.getRes().getOutputStream());BufferedInputStream bis new BufferedInputStream(minioFileUtil.getObject(bucketName, bo.getFileName(), startPos, rangLength))) {IOUtils.copy(bis, bos);} catch (IOException e) {if (e instanceof ClientAbortException) {// ignore 这里不打印日志这里的异常原因是用户在拖拽视频进度造成的} else {logger.error(e.getMessage());}}} }com.example.web.rest.file.FileRest package com.example.web.rest.file;import com.alibaba.fastjson2.JSONObject; import com.example.blh.file.FileBlh; import com.example.entity.file.FileBo; import com.example.web.dto.CommResp; import com.example.web.dto.file.FileResp; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;/*** description 文件管理*/ RestController RequestMapping(/api/file) public class FileRest {private static Log logger LogFactory.getLog(FileRest.class);Resourceprivate FileBlh fileBlh;/*** description 直接上传文件, 入参:file, 出参:fileName*/PostMapping(valueuploadFile)public FileResp uploadFileRest(HttpServletRequest req) {FileResp resp new FileResp();FileBo bo new FileBo();bo.setReq(req);fileBlh.uploadFile(bo);resp.setFileName(bo.getFileName());CommResp.setResp(resp,bo);resp.setResp();return resp;}/*** description 获取文件下载Url, 入参:fileName, 出参:fileUrl*/PostMapping(valuegetFileUrl,consumesapplication/json)public FileResp getFileUrlRest(RequestBody JSONObject req) {FileResp resp new FileResp();FileBo bo new FileBo();bo.setFileName(req.getString(fileName));fileBlh.getFileUrl(bo);resp.setFileUrl(bo.getFileUrl());CommResp.setResp(resp,bo);resp.setResp();return resp;}/*** description 删除文件, 入参:fileName*/PostMapping(valuedeleteFile,consumesapplication/json)public FileResp deleteFileRest(RequestBody JSONObject req) {FileResp resp new FileResp();FileBo bo new FileBo();bo.setFileName(req.getString(fileName));fileBlh.deleteFile(bo);CommResp.setResp(resp,bo);resp.setResp();return resp;}/*** description 校验文件是否存在, 入参:md5*/GetMapping(value checkSplitFile)public FileResp checkSplitFileRest(String md5) {FileResp resp new FileResp();FileBo bo new FileBo();bo.setMd5(md5);fileBlh.checkSplitFile(bo);resp.setFileUrl(bo.getFileUrl());resp.setCode(bo.getCode());CommResp.setResp(resp,bo);resp.setResp();return resp;}/*** description 分片上传文件, 入参:data*/PostMapping(value uploadSplitFile)public FileResp uploadSplitFileRest(HttpServletRequest req) {FileResp resp new FileResp();FileBo bo new FileBo();bo.setReq(req);fileBlh.uploadSplitFile(bo);resp.setCode(bo.getCode());CommResp.setResp(resp,bo);resp.setResp();return resp;}/*** description 文件合并, 入参:shardCount/fileName/md5/fileType/fileSize*/GetMapping(value mergeSplitFile)public FileResp mergeSplitFileRest(HttpServletRequest req) {FileResp resp new FileResp();FileBo bo new FileBo();bo.setShardCount(Integer.valueOf(req.getParameter(shardCount)));bo.setFileName(req.getParameter(fileName));bo.setMd5(req.getParameter(md5));bo.setFileType(req.getParameter(fileType));bo.setFileSize(Long.valueOf(req.getParameter(fileSize)));fileBlh.mergeSplitFile(bo);resp.setCode(bo.getCode());resp.setFileName(bo.getFileName());CommResp.setResp(resp,bo);resp.setResp();return resp;}/*** description 获取文件分片下载信息, 入参:fileName, 出参:shardCount*/PostMapping(valuegetSplitFileInfo,consumesapplication/json)public FileResp getSplitFileInfoRest(RequestBody JSONObject req) {FileResp resp new FileResp();FileBo bo new FileBo();bo.setFileName(req.getString(fileName));fileBlh.getSplitFileInfo(bo);resp.setShardCount(bo.getShardCount());CommResp.setResp(resp,bo);resp.setResp();return resp;}/*** description 文件分片下载, 入参:fileName/fileNo, 出参:文件流*/GetMapping(valuedownSplitFile)public void downSplitFileRest(HttpServletRequest req, HttpServletResponse res) {FileBo bo new FileBo();bo.setFileName(req.getParameter(fileName));bo.setShardCount(Integer.valueOf(req.getParameter(fileNo)));bo.setRes(res);fileBlh.downSplitFile(bo);}/*** description 视频播放*/GetMapping(value videoPlay)public void videoPlayRest(HttpServletRequest req, HttpServletResponse res) {FileBo bo new FileBo();bo.setReq(req);bo.setRes(res);bo.setFileName(req.getParameter(video));fileBlh.videoPlay(bo);} }2. 文件上传前端代码 HTML效果 http://127.0.0.1:8081/test/upload.html resources/static/upload.html !DOCTYPE html html langen headmeta charsetUTF-8titleupload/titlelink relicon hrefdata:;base64,script srchttps://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js/scriptscript srchttps://cdn.bootcdn.net/ajax/libs/spark-md5/3.0.2/spark-md5.min.js/script /head bodyinput typefile namefile idfiletext idmsgtext/text /body scriptconst baseUrl http://127.0.0.1:8081/test/api/file//*** 计算文件的md5值* param file 文件*/function calculateFileMd5(file) {return calculateFileMd5Chunk(file, 2097152);}/*** 分片计算文件的md5值* param file 文件* param chunkSize 分片大小*/function calculateFileMd5Chunk(file, chunkSize) {return new Promise((resolve, reject) {let blobSlice File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;let chunks Math.ceil(file.size / chunkSize);let currentChunk 0;let spark new SparkMD5.ArrayBuffer();let fileReader new FileReader();fileReader.onload function (e) {spark.append(e.target.result);currentChunk;if (currentChunk chunks) {loadNext();} else {let md5 spark.end();resolve(md5);}};fileReader.onerror function (e) {reject(e);};function loadNext() {let start currentChunk * chunkSize;let end start chunkSize;if (end file.size) {end file.size;}fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));}loadNext();});}/*** 获取文件的后缀名* param fileName 文件名*/function getFileType(fileName) {return fileName.substring(fileName.lastIndexOf(.) 1).toLowerCase();}/*** 根据文件的md5值判断文件是否已经上传* param md5 文件的md5* param file 准备上传的文件*/function checkMd5(md5, file) {$.ajax({url: baseUrl checkSplitFile,type: get,data: {md5: md5},async: true,dataType: json,success: function (msg) {if (msg.code 200) {console.log(文件已经存在)$(#msgtext).html(文件已存在: msg.fileUrl);} else if (msg.code 204) {console.log(文件不存在需要上传)postFile(file, 0, md5);} else {console.log(未知错误);}}})}/*** 分片上传* param file 上传的文件* param i 第几分片从0开始* param md5 文件的md5值*/function postFile(file, i, md5) {let name file.name, // 文件名size file.size, // 总大小shardSize 2 * 1024 * 1024,shardSize 5 * 1024 * 1024, // 以5MB为一个分片,每个分片的大小shardCount Math.ceil(size / shardSize); // 总片数if (i shardCount) {return;}let start i * shardSize;let end start shardSize;let packet file.slice(start, end); // 将文件进行切片let form new FormData();form.append(md5, md5); // 前端生成uuid作为标识符form.append(data, packet); // slice方法用于切出文件的一部分form.append(name, name);form.append(totalSize, size);form.append(total, shardCount); // 总片数form.append(index, i 1); // 当前是第几片$.ajax({url: baseUrl uploadSplitFile,type: post,data: form,async: true,dataType: json,processData: false,contentType: false,success: function (msg) {if (msg.code 201) {form ;i;postFile(file, i, md5);} else if (msg.code 203) {form ;setInterval(function () {postFile(file, i, md5)}, 2000);} else if (msg.code 202) {merge(shardCount, name, md5, getFileType(file.name), file.size)console.log(上传成功);} else {console.log(未知错误);}}})}/*** 合并文件* param shardCount 分片数* param fileName 文件名* param md5 文件md值* param fileType 文件类型* param fileSize 文件大小*/function merge(shardCount, fileName, md5, fileType, fileSize) {$.ajax({url: baseUrl mergeSplitFile,type: get,data: {shardCount: shardCount,fileName: fileName,md5: md5,fileType: fileType,fileSize: fileSize},async: true,dataType: json,success: function (msg) {$(#msgtext).html(文件上传成功: msg.fileName);}})}// 浏览器加载文件后, 计算文件的md5值document.getElementById(file).addEventListener(change, function () {$(#msgtext).html(待上传);let file this.files[0];calculateFileMd5(file).then(e {let md5 e;checkMd5(md5, file)}).catch(e {console.error(e);});});$(#msgtext).html(待上传); /script /html3. 视频播放前端代码 ckplayer ckplayer是一款在网页上播放视频的软件基于javascript和css其特点是开源不依赖其它插件。 视频播放插件下载、视频播放插件手册 HTML效果 http://127.0.0.1:8081/test/video.html?video202312/f210299b-3988-4ad3-b9a3-fd6677936bda-test.mp4 resources/static/video.html !DOCTYPE html html langen headmeta charsetUTF-8titleplay/titlelink relicon hrefdata:;base64,script srchttps://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js/scriptscript srchttps://www.ckplayer.com/public/static/ckplayer-x3/js/ckplayer.js/scriptlink relstylesheet typetext/css hrefhttps://www.ckplayer.com/public/static/ckplayer-x3/css/ckplayer.css / /head bodydiv classvideo stylewidth: 100%; height: 500px;max-width: 800px;/divpbutton typebutton onclickplayer.play()播放/buttonbutton typebutton onclickplayer.pause()暂停/buttonbutton typebutton onclickplayer.seek(20)跳转/buttonbutton typebutton onclickplayer.volume(0.6)修改音量/buttonbutton typebutton onclickplayer.muted()静音/buttonbutton typebutton onclickplayer.exitMuted()恢复音量/buttonbutton typebutton onclickplayer.full()全屏/button/pp idstate1/pp idstate2/p /body scriptconst queryString window.location.search;const urlParams new URLSearchParams(queryString);const videoObj urlParams.get(video);const baseUrl http://127.0.0.1:8081/test/api/file/videoPlaylet videoObject {container: .video, // 视频容器的IDvolume: 0.8, // 默认音量范围0-1video: baseUrl ?video videoObj, // 视频地址};let player new ckplayer(videoObject) // 调用播放器并赋值给变量player /script /html
http://www.pierceye.com/news/409923/

相关文章:

  • 做网站建设涉及哪些算法呼和浩特网站建设电话
  • 网站流量统计 设计做seo需要会网站开发吗
  • 网站前台用什么开发襄阳谷城网站建设
  • 网站icp备案号怎么查北京 网站建设 SEO
  • 西安做网站哪里好wordpress用户前端化
  • 宁波网站优化如何免费加速器
  • 一佰互联自助建站网站公司建设网站价格
  • 外贸网站模板免费下载wordpress英文显示改中文字体
  • 长春电商网站建设公司电话微博内容放到wordpress
  • 网站销售怎么样的商务网站模块设计时前台基础设施建设
  • 进空间的网站吗帝国建站教程
  • 做网站 业务流程图如何选择丹阳网站建设
  • 金属东莞网站建设技术支持开放平台产品经理
  • 全网营销型的网站苏州网站设计多少钱
  • 河南教育平台网站建设北京市工程建设信息交易网站
  • 正规品牌网站设计推荐如何上传自己的做的网站
  • 企业网站优化甲薇g71679做同等效果下拉词制作手机网站哪家好
  • 物流运输做网站的素材多用户商城系统价格
  • 营销型网站建设流程电脑怎么建网站
  • 郑州市汉狮做网站360免费建站
  • 安阳哪里有学做网站的学校做个公众号需要多少钱
  • 建站seo是什么成都做营销型网站
  • 网站建设哪个wordpress分类title
  • 建手机网站多少钱挂机软件定制
  • 网站建设 提案 框架河南一般建一个网站需要多少钱
  • 福建省建设人才市场网站深圳营销型网站建设优化
  • 晋城购物网站开发设计宣传网站有哪些
  • 在哪人网站要以接it项目做企业为什么要分析环境
  • 达令的网站建设wordpress上传视频
  • 织梦免费网站模块下载地址南充楼盘网