Pārlūkot izejas kodu

处理 http range 请求

reghao 3 gadi atpakaļ
vecāks
revīzija
cd48f926f3

+ 105 - 51
src/main/java/cn/reghao/dfs/store/oss/service/ObjectServiceImpl.java

@@ -18,6 +18,7 @@ import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletResponse;
 import java.io.*;
+import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import java.util.*;
 
@@ -127,79 +128,42 @@ public class ObjectServiceImpl implements ObjectService {
             response.getOutputStream().write("".getBytes(StandardCharsets.UTF_8));
             return;
         }
-        String objectId = fileMeta.getObjectId();
 
+        String objectId = fileMeta.getObjectId();
         String contentType = fileMeta.getContentType();
         long len = fileMeta.getSize();
+        if (len < partLength) {
+            writeWholeContent(objectId, contentType, len);
+            return;
+        }
 
         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 && start == 0) {
-                writeAcceptRanges1(objectId, contentType, len);
+            if (arr.length == 1) {
+                writePartialContent(objectId, contentType, start, len);
             } else {
                 ContentRange contentRange = parseContentRange(range, len);
                 byte[] bytes = range1(objectId, contentRange.getStart(), contentRange.getEnd());
-                writeContent(bytes, HttpServletResponse.SC_PARTIAL_CONTENT, contentType, contentRange, len);
+                writePartialContent(bytes, contentType, contentRange, len);
             }
         } else {
-            writeAcceptRanges(objectId, contentType, len);
+            writeAcceptRanges(contentType, len);
+            //writeDownloadContent(objectName, objectId, 0, len);
         }
     }
 
-    private void writeAcceptRanges(String objectId, String contentType, long len) throws IOException {
+    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");
-        //response.setHeader("Content-Range", "bytes "+0+"-"+(len-1)+"/"+len);
 
         OutputStream outputStream = response.getOutputStream();
-        List<DataBlock> list = dataBlockMapper.findByObjectId(objectId);
-        for (DataBlock dataBlock : list) {
-            String blockId = dataBlock.getBlockId();
-            String absolutePath = dataBlock.getAbsolutePath();
-            FileInputStream fis = new FileInputStream(absolutePath);
-
-            // 1MiB
-            int bufSize = 1024*1024;
-            byte[] buf = new byte[bufSize];
-            int readLen;
-            while ((readLen = fis.read(buf, 0, bufSize)) != -1) {
-                outputStream.write(buf, 0, readLen);
-                outputStream.flush();
-            }
-        }
-        outputStream.close();
-    }
-
-    private void writeAcceptRanges1(String objectId, String contentType, long len) throws IOException {
-        HttpServletResponse response = ServletUtil.getResponse();
-        response.setStatus(HttpServletResponse.SC_OK);
-        response.setContentType(contentType);
-        response.setHeader("Content-Length", ""+partLength);
-        response.setHeader("Accept-Ranges", "bytes");
-        response.setHeader("Content-Range", "bytes "+0+"-"+(partLength)+"/"+len);
-
-        OutputStream outputStream = response.getOutputStream();
-        List<DataBlock> list = dataBlockMapper.findByObjectId(objectId);
-        for (DataBlock dataBlock : list) {
-            String blockId = dataBlock.getBlockId();
-            String absolutePath = dataBlock.getAbsolutePath();
-            FileInputStream fis = new FileInputStream(absolutePath);
-
-            // 1MiB
-            int bufSize = 1024*1024;
-            byte[] buf = new byte[bufSize];
-            int readLen;
-            while ((readLen = fis.read(buf, 0, bufSize)) != -1) {
-                outputStream.write(buf, 0, readLen);
-                outputStream.flush();
-            }
-        }
+        outputStream.flush();
         outputStream.close();
     }
 
@@ -222,9 +186,9 @@ public class ObjectServiceImpl implements ObjectService {
         return new ContentRange(start, end);
     }
 
-    private void writeContent(byte[] bytes, int statusCode, String contentType, ContentRange contentRange, long len) throws IOException {
+    private void writePartialContent(byte[] bytes, String contentType, ContentRange contentRange, long len) throws IOException {
         HttpServletResponse response = ServletUtil.getResponse();
-        response.setStatus(statusCode);
+        response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
         response.setContentType(contentType);
         response.setHeader("Content-Length", ""+(contentRange.getEnd()-contentRange.getStart()));
         response.setHeader("Accept-Ranges", "bytes");
@@ -236,6 +200,95 @@ public class ObjectServiceImpl implements ObjectService {
         outputStream.close();
     }
 
+    private void writePartialContent(String objectId, String contentType, long start, long len) throws IOException {
+        HttpServletResponse response = ServletUtil.getResponse();
+        response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
+        response.setContentType(contentType);
+        response.setHeader("Content-Length", ""+(len-start));
+        response.setHeader("Accept-Ranges", "bytes");
+        response.setHeader("Content-Range", "bytes "+start+"-"+(len-1)+"/"+len);
+
+        OutputStream outputStream = response.getOutputStream();
+        List<DataBlock> list = dataBlockMapper.findByObjectId(objectId);
+        DataBlock dataBlock = list.get(0);
+        String blockId = dataBlock.getBlockId();
+        String absolutePath = dataBlock.getAbsolutePath();
+        RandomAccessFile raf = new RandomAccessFile(absolutePath, "r");
+        raf.seek(start);
+
+        // 10MiB
+        int bufSize = 1024*1024*10;
+        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 writeDownloadContent(String objectName, String objectId, long start, long len) {
+        HttpServletResponse response = ServletUtil.getResponse();
+        response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
+        response.setContentType("application/octet-stream");
+        /*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(objectName, StandardCharsets.UTF_8.toString()));
+
+            OutputStream outputStream = response.getOutputStream();
+            List<DataBlock> list = dataBlockMapper.findByObjectId(objectId);
+            DataBlock dataBlock = list.get(0);
+            String blockId = dataBlock.getBlockId();
+            String absolutePath = dataBlock.getAbsolutePath();
+            RandomAccessFile raf = new RandomAccessFile(absolutePath, "r");
+            raf.seek(start);
+
+            // 10MiB
+            int bufSize = 1024*1024*10;
+            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();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private void writeWholeContent(String objectId, String contentType, long len) throws IOException {
+        HttpServletResponse response = ServletUtil.getResponse();
+        response.setStatus(HttpServletResponse.SC_OK);
+        response.setContentType(contentType);
+        response.setHeader("Content-Length", ""+len);
+
+        OutputStream outputStream = response.getOutputStream();
+        List<DataBlock> list = dataBlockMapper.findByObjectId(objectId);
+        DataBlock dataBlock = list.get(0);
+        String blockId = dataBlock.getBlockId();
+        String absolutePath = dataBlock.getAbsolutePath();
+        RandomAccessFile raf = new RandomAccessFile(absolutePath, "r");
+        raf.seek(0);
+
+        // 10MiB
+        int bufSize = 1024*1024*10;
+        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 byte[] range1(String objectId, long start, long end) throws IOException {
         String absolutePath = dataBlockMapper.findByObjectId(objectId).get(0).getAbsolutePath();
         RandomAccessFile raf = new RandomAccessFile(absolutePath, "r");
@@ -243,6 +296,7 @@ public class ObjectServiceImpl implements ObjectService {
         long bufSize = end - start;
         byte[] bytes = new byte[(int) bufSize];
         int readBytes = raf.read(bytes);
+        raf.close();
         return bytes;
     }
 

+ 1 - 1
src/main/resources/application-dev-dev.yml

@@ -1,6 +1,6 @@
 spring:
   datasource:
-    url: jdbc:mysql://localhost:3306/reghao_vid_file_rdb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2b8
+    url: jdbc:mysql://localhost:3306/reghao_oss_rdb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2b8
     username: dev
     password: Dev@123456
 dfs:

+ 1 - 1
src/main/resources/application-dev.yml

@@ -1,6 +1,6 @@
 spring:
   datasource:
-    url: jdbc:mysql://localhost:3306/reghao_vid_file_rdb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2b8
+    url: jdbc:mysql://localhost:3306/reghao_oss_rdb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2b8
     username: dev
     password: Dev@123456
 dfs: