|
@@ -0,0 +1,179 @@
|
|
|
+package cn.minbb.edu.storage;
|
|
|
+
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.core.io.Resource;
|
|
|
+import org.springframework.core.io.UrlResource;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.util.FileSystemUtils;
|
|
|
+import org.springframework.web.multipart.MultipartFile;
|
|
|
+
|
|
|
+import java.io.File;
|
|
|
+import java.io.IOException;
|
|
|
+import java.net.MalformedURLException;
|
|
|
+import java.nio.file.Files;
|
|
|
+import java.nio.file.Path;
|
|
|
+import java.nio.file.Paths;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.List;
|
|
|
+import java.util.stream.Stream;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class StorageServiceFileSystem implements StorageService {
|
|
|
+
|
|
|
+ private Logger logger = LoggerFactory.getLogger(StorageServiceFileSystem.class);
|
|
|
+
|
|
|
+ private Path rootLocation;
|
|
|
+
|
|
|
+ private StorageProperties storageProperties;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ public StorageServiceFileSystem(StorageProperties properties) {
|
|
|
+ this.storageProperties = properties;
|
|
|
+ this.rootLocation = Paths.get(properties.getLocation());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初始化存储空间(各文件夹)
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public void init() {
|
|
|
+ try {
|
|
|
+ File rootDir = rootLocation.toFile();
|
|
|
+ File imageDir = new File(storageProperties.getImages());
|
|
|
+ File videoDir = new File(storageProperties.getVideos());
|
|
|
+ File avatarDir = new File(storageProperties.getAvatars());
|
|
|
+ File downloadDir = new File(storageProperties.getDownload());
|
|
|
+ List<File> dirList = new ArrayList<>(4);
|
|
|
+ dirList.add(imageDir);
|
|
|
+ dirList.add(videoDir);
|
|
|
+ dirList.add(avatarDir);
|
|
|
+ dirList.add(downloadDir);
|
|
|
+ if (!rootDir.exists()) {
|
|
|
+ Files.createDirectory(rootLocation);
|
|
|
+ }
|
|
|
+ for (File dir : dirList) {
|
|
|
+ if (!dir.exists()) {
|
|
|
+ Files.createDirectory(dir.toPath());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (IOException e) {
|
|
|
+ throw new StorageException("初始化存储空间失败!", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 存储文件
|
|
|
+ *
|
|
|
+ * @param file MultipartFile
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public void store(MultipartFile file) {
|
|
|
+ try {
|
|
|
+ if (file.isEmpty()) {
|
|
|
+ throw new StorageException("Failed to store empty file " + file.getOriginalFilename());
|
|
|
+ }
|
|
|
+ Files.copy(file.getInputStream(), this.rootLocation.resolve(file.getOriginalFilename()));
|
|
|
+ } catch (IOException e) {
|
|
|
+ throw new StorageException("Failed to store file " + file.getOriginalFilename(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除单个文件
|
|
|
+ *
|
|
|
+ * @param filename 文件名
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public void delete(String filename) {
|
|
|
+ try {
|
|
|
+ Files.delete(load(filename));
|
|
|
+ } catch (IOException e) {
|
|
|
+ throw new StorageException("Failed to delete file " + filename, e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除存储空间全部文件(递归删除)
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public void deleteAll() {
|
|
|
+ FileSystemUtils.deleteRecursively(rootLocation.toFile());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 通过文件名加载路径
|
|
|
+ *
|
|
|
+ * @param filename 文件名
|
|
|
+ * @return Path
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public Path load(String filename) {
|
|
|
+ return rootLocation.resolve(filename);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 加载全部文件(通过遍历文件夹而非数据库文件名)
|
|
|
+ *
|
|
|
+ * @return Stream<Path>
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public Stream<Path> loadAll() {
|
|
|
+ try {
|
|
|
+ return Files.walk(this.rootLocation, 1)
|
|
|
+ .filter(path -> !path.equals(this.rootLocation))
|
|
|
+ .map(path -> rootLocation.relativize(path));
|
|
|
+ } catch (IOException e) {
|
|
|
+ throw new StorageException("Failed to read stored files", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 通过文件名加载资源
|
|
|
+ *
|
|
|
+ * @param filename 文件名
|
|
|
+ * @return 文件资源
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public Resource loadAsResource(String filename) {
|
|
|
+ try {
|
|
|
+ Path file = load(filename);
|
|
|
+ Resource resource = new UrlResource(file.toUri());
|
|
|
+ if (resource.exists() || resource.isReadable()) {
|
|
|
+ return resource;
|
|
|
+ } else {
|
|
|
+ throw new StorageFileNotFoundException("Could not read file: " + filename);
|
|
|
+ }
|
|
|
+ } catch (MalformedURLException e) {
|
|
|
+ throw new StorageFileNotFoundException("Could not read file: " + filename, e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 存储文件到文件夹
|
|
|
+ *
|
|
|
+ * @param file 文件
|
|
|
+ * @param path 存储路径
|
|
|
+ * @return 存储成功返回文件名 失败返回空
|
|
|
+ */
|
|
|
+ public String storeToDictionary(MultipartFile file, Path path) {
|
|
|
+ String originalFilename = file.getOriginalFilename();
|
|
|
+ if (null == originalFilename) {
|
|
|
+ logger.error("文件名不能为空:{}", file);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ String fileName = System.currentTimeMillis() + originalFilename.substring(originalFilename.lastIndexOf("."));
|
|
|
+ try {
|
|
|
+ if (file.isEmpty()) {
|
|
|
+ logger.error("文件不能为空:{}", originalFilename);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ Files.copy(file.getInputStream(), path.resolve(fileName));
|
|
|
+ } catch (IOException e) {
|
|
|
+ logger.error("存储失败,原因为:{}", e);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return fileName;
|
|
|
+ }
|
|
|
+}
|