|
|
@@ -1,377 +0,0 @@
|
|
|
-package cn.reghao.dfs.store.service;
|
|
|
-
|
|
|
-import cn.reghao.dfs.store.cache.LocalCache;
|
|
|
-import cn.reghao.dfs.store.db.mapper.DataBlockMapper;
|
|
|
-import cn.reghao.dfs.store.db.mapper.FileContentMapper;
|
|
|
-import cn.reghao.dfs.store.db.mapper.FileMetaMapper;
|
|
|
-import cn.reghao.dfs.store.model.po.ContentRange;
|
|
|
-import cn.reghao.dfs.store.model.po.DataBlock;
|
|
|
-import cn.reghao.dfs.store.model.po.FileContent;
|
|
|
-import cn.reghao.dfs.store.model.po.FileMeta;
|
|
|
-import cn.reghao.dfs.store.model.vo.ObjectMeta;
|
|
|
-import cn.reghao.dfs.store.redis.ds.RedisStringObj;
|
|
|
-import cn.reghao.jutil.jdk.security.DigestUtil;
|
|
|
-import cn.reghao.jutil.tool.id.IdGenerator;
|
|
|
-import cn.reghao.jutil.web.ServletUtil;
|
|
|
-import lombok.extern.slf4j.Slf4j;
|
|
|
-import org.apache.tika.Tika;
|
|
|
-import org.springframework.stereotype.Service;
|
|
|
-import org.springframework.transaction.annotation.Transactional;
|
|
|
-import org.springframework.util.StringUtils;
|
|
|
-
|
|
|
-import javax.servlet.http.HttpServletResponse;
|
|
|
-import java.io.*;
|
|
|
-import java.net.URLEncoder;
|
|
|
-import java.nio.channels.FileChannel;
|
|
|
-import java.nio.channels.WritableByteChannel;
|
|
|
-import java.nio.charset.StandardCharsets;
|
|
|
-import java.nio.file.Files;
|
|
|
-import java.nio.file.Path;
|
|
|
-import java.util.ArrayList;
|
|
|
-import java.util.List;
|
|
|
-import java.util.UUID;
|
|
|
-
|
|
|
-/**
|
|
|
- * @author reghao
|
|
|
- * @date 2022-11-23 09:40:18
|
|
|
- */
|
|
|
-@Slf4j
|
|
|
-@Service
|
|
|
-public class ObjectBasicService {
|
|
|
- private final IdGenerator objectIdGenerator;
|
|
|
- private final IdGenerator blockIdGenerator;
|
|
|
- private final FileMetaMapper fileMetaMapper;
|
|
|
- private FileContentMapper fileContentMapper;
|
|
|
- private final DataBlockMapper dataBlockMapper;
|
|
|
- // 10MiB
|
|
|
- private final int partLength = 1024*1024*10;
|
|
|
- private final FileStoreService fileStoreService;
|
|
|
- private final FileUrlService fileUrlService;
|
|
|
- private final FileTypeService fileTypeService;
|
|
|
- private final LocalCache localCache;
|
|
|
- private final RedisStringObj redisStringObj;
|
|
|
- private Tika tika = new Tika();
|
|
|
-
|
|
|
- public ObjectBasicService(FileMetaMapper fileMetaMapper, FileContentMapper fileContentMapper,
|
|
|
- DataBlockMapper dataBlockMapper,
|
|
|
- FileStoreService fileStoreService, FileUrlService fileUrlService,
|
|
|
- FileTypeService fileTypeService, LocalCache localCache,
|
|
|
- RedisStringObj redisStringObj) {
|
|
|
- this.objectIdGenerator = new IdGenerator(32, "object-id");
|
|
|
- this.blockIdGenerator = new IdGenerator(32, "block-id");
|
|
|
- this.fileMetaMapper = fileMetaMapper;
|
|
|
- this.fileContentMapper = fileContentMapper;
|
|
|
- this.dataBlockMapper = dataBlockMapper;
|
|
|
- this.fileStoreService = fileStoreService;
|
|
|
- this.fileUrlService = fileUrlService;
|
|
|
- this.fileTypeService = fileTypeService;
|
|
|
- this.localCache = localCache;
|
|
|
- this.redisStringObj = redisStringObj;
|
|
|
- }
|
|
|
-
|
|
|
- @Transactional(rollbackFor = Exception.class)
|
|
|
- public void putObject(String objectName, File file, String sha256sum) throws Exception {
|
|
|
- String[] names = objectName.split("/");
|
|
|
- String filename = names[names.length-1];
|
|
|
-
|
|
|
- String contentType = tika.detect(file);
|
|
|
- FileMeta fileMeta2 = fileMetaMapper.findByObjectName(objectName);
|
|
|
- if (fileMeta2 != null) {
|
|
|
- String sha256sum1 = fileMeta2.getSha256sum();
|
|
|
- if (sha256sum1.equals(sha256sum)) {
|
|
|
- log.info("{} 内容没有变化", objectName);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- log.info("更新对象操作暂未实现");
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- addParent(objectName);
|
|
|
- List<FileMeta> list = fileMetaMapper.findBySha256sum(sha256sum);
|
|
|
- if (list.isEmpty()) {
|
|
|
- String objectId = objectIdGenerator.stringId();
|
|
|
- String contentId = UUID.randomUUID().toString().replace("-", "");
|
|
|
- FileContent fileContent = new FileContent(contentId, objectId);
|
|
|
- long len = file.length();
|
|
|
- List<DataBlock> blocks = store(objectId, len, file);
|
|
|
- int fileTypeId = fileTypeService.getFileType1(contentType);
|
|
|
- FileMeta fileMeta = new FileMeta(objectName, objectId, filename, len, fileTypeId, contentType, sha256sum, "tnb", 2);
|
|
|
-
|
|
|
- fileMetaMapper.save(fileMeta);
|
|
|
- fileContentMapper.save(fileContent);
|
|
|
- dataBlockMapper.saveAll(blocks);
|
|
|
- } else {
|
|
|
- FileMeta fileMeta = list.get(0);
|
|
|
- String contentId = fileContentMapper.findContentId(fileMeta.getObjectId());
|
|
|
- String objectId = UUID.randomUUID().toString().replace("-", "");
|
|
|
- FileContent fileContent = new FileContent(contentId, objectId);
|
|
|
- FileMeta fileMeta1 = new FileMeta(objectName, objectId, filename, fileMeta);
|
|
|
-
|
|
|
- fileMetaMapper.save(fileMeta1);
|
|
|
- fileContentMapper.save(fileContent);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private void addParent(String objectName) {
|
|
|
- List<String> list = getParent(objectName);
|
|
|
- List<FileMeta> fileMetas = new ArrayList<>();
|
|
|
- list.forEach(parentName -> {
|
|
|
- FileMeta fileMeta = fileMetaMapper.findByObjectName(parentName);
|
|
|
- if (fileMeta == null) {
|
|
|
- fileMetas.add(new FileMeta(parentName, 2));
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- if (!fileMetas.isEmpty()) {
|
|
|
- fileMetaMapper.saveAll(fileMetas);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private List<String> getParent(String objectName) {
|
|
|
- String[] arr = objectName.split("/");
|
|
|
- List<String> list = new ArrayList<>();
|
|
|
- list.add(arr[0] + "/");
|
|
|
- for (int i = 1; i < arr.length-1; i++) {
|
|
|
- list.add(list.get(i-1) + arr[i] + "/");
|
|
|
- }
|
|
|
- return list;
|
|
|
- }
|
|
|
-
|
|
|
- public void postObject(String objectName, long len, String contentType, InputStream inputStream) throws Exception {
|
|
|
- }
|
|
|
-
|
|
|
- private List<DataBlock> store(String objectId, long len, File file) throws IOException {
|
|
|
- FileInputStream fis = new FileInputStream(file);
|
|
|
- FileChannel inputChannel = fis.getChannel();
|
|
|
-
|
|
|
- List<DataBlock> list = new ArrayList<>();
|
|
|
- String absolutePath = fileUrlService.genFilePath(len, objectId, "dat");
|
|
|
- FileOutputStream fos = new FileOutputStream(absolutePath);
|
|
|
- WritableByteChannel targetChannel = fos.getChannel();
|
|
|
- inputChannel.transferTo(0, inputChannel.size(), targetChannel);
|
|
|
- Files.delete(file.toPath());
|
|
|
-
|
|
|
- String blockId = UUID.randomUUID().toString();
|
|
|
- list.add(new DataBlock(objectId, 0, blockId, absolutePath));
|
|
|
- return list;
|
|
|
- }
|
|
|
-
|
|
|
- private List<DataBlock> store(String objectId, long len, InputStream inputStream) throws IOException {
|
|
|
- List<DataBlock> list = new ArrayList<>();
|
|
|
- String absolutePath = fileUrlService.genFilePath(len, objectId, "dat");
|
|
|
- fileStoreService.saveFile(absolutePath, inputStream);
|
|
|
-
|
|
|
- String blockId = UUID.randomUUID().toString();
|
|
|
- list.add(new DataBlock(objectId, 0, blockId, absolutePath));
|
|
|
- return list;
|
|
|
- }
|
|
|
-
|
|
|
- public void headObject(String objectName) throws IOException {
|
|
|
- HttpServletResponse response = ServletUtil.getResponse();
|
|
|
- FileMeta fileMeta = fileMetaMapper.findByObjectName(objectName);
|
|
|
- if (fileMeta == null) {
|
|
|
- response.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
|
|
-
|
|
|
- OutputStream outputStream = response.getOutputStream();
|
|
|
- outputStream.flush();
|
|
|
- outputStream.close();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public void getObject(String objectName) throws IOException {
|
|
|
- String userAgent = ServletUtil.getRequest().getHeader("user-agent");
|
|
|
- String host = ServletUtil.getRequest().getHeader("host");
|
|
|
- HttpServletResponse response = ServletUtil.getResponse();
|
|
|
-
|
|
|
- ObjectMeta objectMeta;
|
|
|
- Object object = redisStringObj.get(objectName);
|
|
|
- if (object != null) {
|
|
|
- objectMeta = (ObjectMeta) object;
|
|
|
- } else {
|
|
|
- objectMeta = fileMetaMapper.findObjectMeta(objectName);
|
|
|
- }
|
|
|
-
|
|
|
- if (objectMeta == null) {
|
|
|
- response.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
|
|
- OutputStream outputStream = response.getOutputStream();
|
|
|
- outputStream.flush();
|
|
|
- outputStream.close();
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- long len = objectMeta.getSize();
|
|
|
- String range = ServletUtil.getRequest().getHeader("range");
|
|
|
- if (range != null) {
|
|
|
- String rangeStr = StringUtils.trimAllWhitespace(range);
|
|
|
- String[] arr = rangeStr.replace("bytes=", "").split("-");
|
|
|
- long start = Long.parseLong(arr[0]);
|
|
|
- if (arr.length == 1) {
|
|
|
- writeContentRange(objectMeta, start, objectMeta.getSize());
|
|
|
- } else {
|
|
|
- ContentRange contentRange = parseContentRange(range, len);
|
|
|
- writeContentRange(objectMeta, contentRange.getStart(), contentRange.getEnd());
|
|
|
- }
|
|
|
- } else {
|
|
|
- if (userAgent.contains("aws-sdk-java") || host.contains("oss.reghao.cn")) {
|
|
|
- writeDownloadContent(objectMeta);
|
|
|
- } else {
|
|
|
- writeWholeContent(objectMeta);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private void writeAcceptRanges(String contentType, long len) throws IOException {
|
|
|
- HttpServletResponse response = ServletUtil.getResponse();
|
|
|
- response.setStatus(HttpServletResponse.SC_OK);
|
|
|
- response.setContentType(contentType);
|
|
|
- response.setHeader("Content-Length", ""+len);
|
|
|
- response.setHeader("Accept-Ranges", "bytes");
|
|
|
-
|
|
|
- OutputStream outputStream = response.getOutputStream();
|
|
|
- outputStream.flush();
|
|
|
- outputStream.close();
|
|
|
- }
|
|
|
-
|
|
|
- private ContentRange parseContentRange(String range, long len) {
|
|
|
- String rangeStr = StringUtils.trimAllWhitespace(range);
|
|
|
- String[] arr = rangeStr.replace("bytes=", "").split("-");
|
|
|
- long start = Long.parseLong(arr[0]);
|
|
|
- long end = 0;
|
|
|
- if (arr.length == 2) {
|
|
|
- end = Long.parseLong(arr[1]);
|
|
|
- } else {
|
|
|
- long l = len - start;
|
|
|
- if (l > 0) {
|
|
|
- end = Math.min(l, partLength) + start;
|
|
|
- } else {
|
|
|
- System.out.println();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return new ContentRange(start, end);
|
|
|
- }
|
|
|
-
|
|
|
- private void writeContentRange(ObjectMeta objectMeta, long start, long end) throws IOException {
|
|
|
- long contentLength = objectMeta.getSize();
|
|
|
- HttpServletResponse response = ServletUtil.getResponse();
|
|
|
- response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
|
|
|
- response.setContentType(objectMeta.getContentType());
|
|
|
- response.setHeader("Content-Length", ""+contentLength);
|
|
|
- response.setHeader("Accept-Ranges", "bytes");
|
|
|
- response.setHeader("Content-Range", "bytes "+start+"-"+(end-1)+"/"+contentLength);
|
|
|
-
|
|
|
- OutputStream outputStream = response.getOutputStream();
|
|
|
- RandomAccessFile raf;
|
|
|
- String cachePath = localCache.getCache(objectMeta.getObjectId());
|
|
|
- if (cachePath != null && Files.exists(Path.of(cachePath))) {
|
|
|
- raf = new RandomAccessFile(cachePath, "r");
|
|
|
- } else {
|
|
|
- raf = new RandomAccessFile(objectMeta.getAbsolutePath(), "r");
|
|
|
- }
|
|
|
- raf.seek(start);
|
|
|
-
|
|
|
- byte[] buf = new byte[partLength];
|
|
|
- int readLen;
|
|
|
- while ((readLen = raf.read(buf, 0, partLength)) != -1) {
|
|
|
- outputStream.write(buf, 0, readLen);
|
|
|
- outputStream.flush();
|
|
|
- }
|
|
|
- outputStream.close();
|
|
|
- raf.close();
|
|
|
- }
|
|
|
-
|
|
|
- private void writeDownloadContent(ObjectMeta objectMeta) {
|
|
|
- HttpServletResponse response = ServletUtil.getResponse();
|
|
|
- response.setStatus(HttpServletResponse.SC_OK);
|
|
|
- response.setContentType(objectMeta.getContentType());
|
|
|
- response.setHeader("Content-Length", ""+objectMeta.getSize());
|
|
|
- /*response.setHeader("Content-Length", ""+(len-start));
|
|
|
- response.setHeader("Accept-Ranges", "bytes");
|
|
|
- response.setHeader("Content-Range", "bytes "+start+"-"+(len-1)+"/"+len);*/
|
|
|
-
|
|
|
- try {
|
|
|
- response.setHeader("Content-Disposition", "attachment;filename=" +
|
|
|
- URLEncoder.encode(objectMeta.getObjectName(), StandardCharsets.UTF_8.toString()));
|
|
|
-
|
|
|
- OutputStream outputStream = response.getOutputStream();
|
|
|
- String absolutePath = objectMeta.getAbsolutePath();
|
|
|
- RandomAccessFile raf = new RandomAccessFile(absolutePath, "r");
|
|
|
- raf.seek(0);
|
|
|
-
|
|
|
- byte[] buf = new byte[partLength];
|
|
|
- int readLen;
|
|
|
- while ((readLen = raf.read(buf, 0, partLength)) != -1) {
|
|
|
- outputStream.write(buf, 0, readLen);
|
|
|
- }
|
|
|
- outputStream.flush();
|
|
|
- outputStream.close();
|
|
|
- raf.close();
|
|
|
- } catch (IOException e) {
|
|
|
- e.printStackTrace();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private void writeDownloadContentSdk(ObjectMeta objectMeta) {
|
|
|
- HttpServletResponse response = ServletUtil.getResponse();
|
|
|
- response.setStatus(HttpServletResponse.SC_OK);
|
|
|
- response.setContentType(objectMeta.getContentType());
|
|
|
- response.setHeader("Content-Length", ""+objectMeta.getSize());
|
|
|
- /*response.setHeader("Accept-Ranges", "bytes");
|
|
|
- response.setHeader("Content-Range", "bytes "+start+"-"+(len-1)+"/"+len);*/
|
|
|
-
|
|
|
- try {
|
|
|
- response.setHeader("Content-Disposition", "attachment;filename=" +
|
|
|
- URLEncoder.encode(objectMeta.getObjectName(), StandardCharsets.UTF_8.toString()));
|
|
|
-
|
|
|
- OutputStream outputStream = response.getOutputStream();
|
|
|
- String absolutePath = objectMeta.getAbsolutePath();
|
|
|
- RandomAccessFile raf = new RandomAccessFile(absolutePath, "r");
|
|
|
- raf.seek(0);
|
|
|
-
|
|
|
- byte[] buf = new byte[partLength];
|
|
|
- int readLen;
|
|
|
- while ((readLen = raf.read(buf, 0, partLength)) != -1) {
|
|
|
- outputStream.write(buf, 0, readLen);
|
|
|
- }
|
|
|
- outputStream.flush();
|
|
|
- outputStream.close();
|
|
|
- raf.close();
|
|
|
- } catch (IOException e) {
|
|
|
- e.printStackTrace();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private void writeWholeContent(ObjectMeta objectMeta) throws IOException {
|
|
|
- HttpServletResponse response = ServletUtil.getResponse();
|
|
|
- response.setStatus(HttpServletResponse.SC_OK);
|
|
|
- response.setContentType(objectMeta.getContentType());
|
|
|
- response.setHeader("Content-Length", ""+objectMeta.getSize());
|
|
|
-
|
|
|
- OutputStream outputStream = response.getOutputStream();
|
|
|
- RandomAccessFile raf = new RandomAccessFile(objectMeta.getAbsolutePath(), "r");
|
|
|
-
|
|
|
- // 1MiB
|
|
|
- int bufSize = 1024*1024;
|
|
|
- byte[] buf = new byte[bufSize];
|
|
|
- int readLen;
|
|
|
- while ((readLen = raf.read(buf, 0, bufSize)) != -1) {
|
|
|
- outputStream.write(buf, 0, readLen);
|
|
|
- }
|
|
|
- outputStream.flush();
|
|
|
- outputStream.close();
|
|
|
- raf.close();
|
|
|
- }
|
|
|
-
|
|
|
- private void writeResponse(String absolutePath, long start, long end) {
|
|
|
- }
|
|
|
-
|
|
|
- public void deleteObject(String objectName) {
|
|
|
- }
|
|
|
-
|
|
|
- public void deleteMultipleObjects() {
|
|
|
- }
|
|
|
-
|
|
|
- public void putObjectCopy() {
|
|
|
- }
|
|
|
-}
|