Pārlūkot izejas kodu

优化本地文件上传逻辑,一次读流,完成写出和md5获取

zhouhao 7 gadi atpakaļ
vecāks
revīzija
70450f1cf6

+ 50 - 10
hsweb-system/hsweb-system-file/hsweb-system-file-service/hsweb-system-file-service-simple/src/main/java/org/hswebframework/web/service/file/simple/LocalFileService.java

@@ -1,5 +1,6 @@
 package org.hswebframework.web.service.file.simple;
 
+import org.apache.commons.codec.binary.Hex;
 import org.apache.commons.codec.digest.DigestUtils;
 import org.hswebframework.utils.time.DateFormatter;
 import org.hswebframework.web.NotFoundException;
@@ -7,12 +8,15 @@ import org.hswebframework.web.commons.entity.DataStatus;
 import org.hswebframework.web.entity.file.FileInfoEntity;
 import org.hswebframework.web.service.file.FileInfoService;
 import org.hswebframework.web.service.file.FileService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.util.StreamUtils;
 
 import java.io.*;
+import java.security.MessageDigest;
 import java.util.Date;
 
 /**
@@ -25,6 +29,7 @@ import java.util.Date;
 public class LocalFileService implements FileService {
     private FileInfoService fileInfoService;
 
+    private Logger logger = LoggerFactory.getLogger(this.getClass());
     /**
      * 静态文件存储目录,不能以/结尾
      */
@@ -129,20 +134,54 @@ public class LocalFileService implements FileService {
         }
         String newName = String.valueOf(System.nanoTime()); //临时文件名 ,纳秒的md5值
         String fileAbsName = absPath.concat("/").concat(newName);
-        long fileLength;
-        try (BufferedInputStream in = new BufferedInputStream(fileStream);
-             FileOutputStream os = new FileOutputStream(fileAbsName)) {
-            fileLength = StreamUtils.copy(in, os);
+        int fileSize;
+        MessageDigest digest = DigestUtils.getMd5Digest();
+
+        try (InputStream in =new InputStream() {
+            @Override
+            public int read(byte[] b, int off, int len) throws IOException {
+                int l = fileStream.read(b, off, len);
+                digest.update(b, off, len);
+                return l;
+            }
+
+            @Override
+            public void close() throws IOException {
+                fileStream.close();
+                super.close();
+            }
+
+            @Override
+            public int available() throws IOException {
+                return fileStream.available();
+            }
+
+            @Override
+            public int read() throws IOException {
+                return fileStream.read();
+            }
+        }; FileOutputStream os = new FileOutputStream(fileAbsName)) {
+            int remainBytes=fileSize= in.available();
+            byte[] buff = new byte[remainBytes>1024*10?1024*10:remainBytes];
+            int bytes;
+            logger.info("开始写出文件:{}到:{}, size: {} bytes",fileName,fileAbsName,fileSize);
+            while (remainBytes > 0) {
+                bytes = in.read(buff, 0, remainBytes > buff.length ? buff.length :  remainBytes);
+                os.write(buff, 0, bytes);
+                remainBytes -= bytes;
+                logger.info("写出文件:{}:{},剩余数据量: {} bytes",fileName,fileAbsName, remainBytes);
+            }
+           // StreamUtils.copy(in, os);
         }
+
+        String md5 = Hex.encodeHexString(digest.digest());
+
         File newFile = new File(fileAbsName);
         //获取文件的md5值
-        String md5;
-        try (FileInputStream inputStream = new FileInputStream(newFile)) {
-            md5 = DigestUtils.md5Hex(inputStream);
-        }
-        //  判断文件是否已经存在
+        //判断文件是否已经存在
         FileInfoEntity fileInfo = fileInfoService.selectByMd5(md5);
         if (fileInfo != null) {
+            logger.info("文件:{}已上传过",fileAbsName);
             if (new File(getFilePath() + "/" + fileInfo.getLocation()).exists()) {
                 newFile.delete();//文件已存在则删除临时文件不做处理
             } else {
@@ -150,6 +189,7 @@ public class LocalFileService implements FileService {
             }
             return fileInfo;
         } else {
+            logger.info("上传文件{}完成:{}->{}",fileName,fileAbsName,absPath.concat("/").concat(md5));
             newFile.renameTo(new File(absPath.concat("/").concat(md5)));
         }
         FileInfoEntity infoEntity = fileInfoService.createEntity();
@@ -158,7 +198,7 @@ public class LocalFileService implements FileService {
         infoEntity.setLocation(filePath.concat("/").concat(md5));
         infoEntity.setName(fileName);
         infoEntity.setType(type);
-        infoEntity.setSize(fileLength);
+        infoEntity.setSize((long)fileSize);
         infoEntity.setMd5(md5);
         infoEntity.setStatus(DataStatus.STATUS_ENABLED);
         fileInfoService.insert(infoEntity);