|
|
@@ -0,0 +1,263 @@
|
|
|
+package com.goldenwater.slgc.service.impl.efinder;
|
|
|
+
|
|
|
+import com.goldenwater.slgc.entity.efinder.DocFile;
|
|
|
+import com.goldenwater.slgc.mapper.efinder.DocFileMapper;
|
|
|
+import com.goldenwater.slgc.service.efinder.IDocFileService;
|
|
|
+import com.goldenwater.common.config.RuoYiConfig;
|
|
|
+import com.goldenwater.common.utils.file.FileUtils;
|
|
|
+import com.goldenwater.common.utils.file.FileUploadUtils;
|
|
|
+import jakarta.servlet.http.HttpServletResponse;
|
|
|
+import org.apache.commons.io.IOUtils;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.web.multipart.MultipartFile;
|
|
|
+
|
|
|
+import java.io.File;
|
|
|
+import java.io.FileInputStream;
|
|
|
+import java.io.IOException;
|
|
|
+import java.io.InputStream;
|
|
|
+import java.io.OutputStream;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Collections;
|
|
|
+import java.util.Date;
|
|
|
+import java.util.Enumeration;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.zip.ZipEntry;
|
|
|
+import java.util.zip.ZipFile;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class DocFileServiceImpl implements IDocFileService {
|
|
|
+ @Autowired
|
|
|
+ private DocFileMapper docFileMapper;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查询文件列表
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public List<DocFile> selectList(DocFile docFile) {
|
|
|
+ return docFileMapper.selectList(docFile);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据主键查询文件
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public DocFile selectById(Long id) {
|
|
|
+ return docFileMapper.selectById(id);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 下载文件
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public void download(Long id, HttpServletResponse response) {
|
|
|
+ DocFile docFile = docFileMapper.selectById(id);
|
|
|
+ if (docFile == null || docFile.getPath() == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ FileUtils.setAttachmentResponseHeader(response, docFile.getName());
|
|
|
+ response.setContentType("application/octet-stream");
|
|
|
+ FileUtils.writeBytes(docFile.getPath(), response.getOutputStream());
|
|
|
+ } catch (IOException e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 上传文件
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public String upload(MultipartFile file) {
|
|
|
+ try {
|
|
|
+ String url = FileUploadUtils.upload(RuoYiConfig.getProfile(), file);
|
|
|
+ String absPath = RuoYiConfig.getProfile() + "/" + url.replace("/profile/", "");
|
|
|
+ DocFile docFile = new DocFile();
|
|
|
+ docFile.setName(file.getOriginalFilename());
|
|
|
+ docFile.setType(FileUploadUtils.getExtension(file));
|
|
|
+ docFile.setSize(file.getSize());
|
|
|
+ docFile.setPath(absPath);
|
|
|
+ docFile.setDate(new Date());
|
|
|
+ docFileMapper.insert(docFile);
|
|
|
+ return url;
|
|
|
+ } catch (IOException e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 新增文件
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public int insert(DocFile docFile) {
|
|
|
+ return docFileMapper.insert(docFile);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 修改文件
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public int update(DocFile docFile) {
|
|
|
+ return docFileMapper.update(docFile);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除文件
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public int deleteById(Long id) {
|
|
|
+ DocFile docFile = docFileMapper.selectById(id);
|
|
|
+ if (docFile != null && docFile.getPath() != null) {
|
|
|
+ FileUtils.deleteFile(docFile.getPath());
|
|
|
+ }
|
|
|
+ return docFileMapper.deleteById(id);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 批量删除文件
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public int deleteByIds(Long[] ids) {
|
|
|
+ for (Long id : ids) {
|
|
|
+ DocFile docFile = docFileMapper.selectById(id);
|
|
|
+ if (docFile != null && docFile.getPath() != null) {
|
|
|
+ FileUtils.deleteFile(docFile.getPath());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return docFileMapper.deleteByIds(ids);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据父ID查询文件列表
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public List<DocFile> selectByParentId(Long parentId) {
|
|
|
+ return docFileMapper.selectByParentId(parentId);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String readTextContent(Long id, String charset) {
|
|
|
+ DocFile docFile = docFileMapper.selectById(id);
|
|
|
+ if (docFile == null || docFile.getPath() == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ File file = new File(docFile.getPath());
|
|
|
+ if (!file.exists() || !file.isFile()) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ if (file.length() > 5 * 1024 * 1024) {
|
|
|
+ throw new RuntimeException("File size exceeds 5MB limit");
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ String enc = (charset != null) ? charset : "UTF-8";
|
|
|
+ return IOUtils.toString(new FileInputStream(file), enc);
|
|
|
+ } catch (IOException e) {
|
|
|
+ throw new RuntimeException("Failed to read text file", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<Map<String, Object>> listZipEntries(Long id) {
|
|
|
+ DocFile docFile = docFileMapper.selectById(id);
|
|
|
+ if (docFile == null || docFile.getPath() == null) {
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+ File file = new File(docFile.getPath());
|
|
|
+ if (!file.exists()) {
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+ List<Map<String, Object>> entries = new ArrayList<>();
|
|
|
+ try (ZipFile zipFile = new ZipFile(file)) {
|
|
|
+ Enumeration<? extends ZipEntry> enumeration = zipFile.entries();
|
|
|
+ while (enumeration.hasMoreElements()) {
|
|
|
+ ZipEntry entry = enumeration.nextElement();
|
|
|
+ Map<String, Object> entryMap = new HashMap<>();
|
|
|
+ entryMap.put("name", entry.getName());
|
|
|
+ entryMap.put("size", entry.getSize());
|
|
|
+ entryMap.put("compressedSize", entry.getCompressedSize());
|
|
|
+ entryMap.put("isDirectory", entry.isDirectory());
|
|
|
+ entries.add(entryMap);
|
|
|
+ }
|
|
|
+ } catch (IOException e) {
|
|
|
+ throw new RuntimeException("Failed to read ZIP file", e);
|
|
|
+ }
|
|
|
+ return entries;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void downloadZipEntry(Long id, String entryPath, HttpServletResponse response) {
|
|
|
+ DocFile docFile = docFileMapper.selectById(id);
|
|
|
+ if (docFile == null || docFile.getPath() == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ File file = new File(docFile.getPath());
|
|
|
+ if (!file.exists()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ try (ZipFile zipFile = new ZipFile(file)) {
|
|
|
+ ZipEntry entry = zipFile.getEntry(entryPath);
|
|
|
+ if (entry == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ String fileName = entry.getName();
|
|
|
+ if (fileName.contains("/")) {
|
|
|
+ fileName = fileName.substring(fileName.lastIndexOf("/") + 1);
|
|
|
+ }
|
|
|
+ FileUtils.setAttachmentResponseHeader(response, fileName);
|
|
|
+ response.setContentType("application/octet-stream");
|
|
|
+ try (InputStream is = zipFile.getInputStream(entry);
|
|
|
+ OutputStream os = response.getOutputStream()) {
|
|
|
+ IOUtils.copy(is, os);
|
|
|
+ os.flush();
|
|
|
+ }
|
|
|
+ } catch (IOException e) {
|
|
|
+ throw new RuntimeException("Failed to download ZIP entry", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void streamMedia(Long id, HttpServletResponse response) {
|
|
|
+ DocFile docFile = docFileMapper.selectById(id);
|
|
|
+ if (docFile == null || docFile.getPath() == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ String contentType = getMediaContentType(docFile.getName());
|
|
|
+ response.setContentType(contentType);
|
|
|
+ FileUtils.writeBytes(docFile.getPath(), response.getOutputStream());
|
|
|
+ } catch (IOException e) {
|
|
|
+ throw new RuntimeException("Failed to stream media file", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getMediaContentType(String fileName) {
|
|
|
+ if (fileName == null) {
|
|
|
+ return "application/octet-stream";
|
|
|
+ }
|
|
|
+ int dotIndex = fileName.lastIndexOf(".");
|
|
|
+ if (dotIndex < 0) {
|
|
|
+ return "application/octet-stream";
|
|
|
+ }
|
|
|
+ String ext = fileName.substring(dotIndex + 1).toLowerCase();
|
|
|
+ switch (ext) {
|
|
|
+ case "mp4": return "video/mp4";
|
|
|
+ case "webm": return "video/webm";
|
|
|
+ case "ogg": return "video/ogg";
|
|
|
+ case "mp3": return "audio/mpeg";
|
|
|
+ case "wav": return "audio/wav";
|
|
|
+ case "flac": return "audio/flac";
|
|
|
+ case "mkv": return "video/x-matroska";
|
|
|
+ case "avi": return "video/x-msvideo";
|
|
|
+ case "mov": return "video/quicktime";
|
|
|
+ case "m3u8": return "application/x-mpegURL";
|
|
|
+ case "ts": return "video/MP2T";
|
|
|
+ case "wma": return "audio/x-ms-wma";
|
|
|
+ case "flv": return "video/x-flv";
|
|
|
+ case "mpeg":
|
|
|
+ case "mpg": return "video/mpeg";
|
|
|
+ default: return "application/octet-stream";
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|