file download range
This commit is contained in:
@@ -31,4 +31,5 @@ public interface IFileStorage {
|
||||
*/
|
||||
InputStream download(String filePath);
|
||||
|
||||
void downloadRange(String filePath, OutputStream outputStream, long start, long length);
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ import com.newyetai.component.file.service.FileClassService;
|
||||
import com.newyetai.component.file.service.FileRecordService;
|
||||
import com.newyetai.component.file.service.FileService;
|
||||
import com.newyetai.component.file.service.IFileStorage;
|
||||
import com.newyetai.component.file.service.storage.AliFileStorage;
|
||||
import com.newyetai.component.file.util.FileUtils;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
@@ -203,7 +204,7 @@ public class FileServiceImpl implements FileService {
|
||||
response.setHeader("Content-Length", String.valueOf(contentLength));
|
||||
|
||||
// 下载指定范围的内容
|
||||
downloadRange(fileRecord.getFilePath(), response.getOutputStream(), start, contentLength);
|
||||
fileStorage.downloadRange(fileRecord.getFilePath(), response.getOutputStream(), start, contentLength);
|
||||
|
||||
} catch (NumberFormatException e) {
|
||||
log.warn("无效的Range请求: {}", rangeHeader);
|
||||
@@ -213,33 +214,6 @@ public class FileServiceImpl implements FileService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载文件的指定范围
|
||||
*/
|
||||
private void downloadRange(String filePath, OutputStream outputStream, long start, long length) throws IOException {
|
||||
try (InputStream inputStream = fileStorage.download(filePath)) {
|
||||
// 跳过开始位置之前的字节
|
||||
long skipped = inputStream.skip(start);
|
||||
if (skipped != start) {
|
||||
log.warn("跳过字节数不匹配,期望: {}, 实际: {}", start, skipped);
|
||||
}
|
||||
|
||||
// 读取指定长度的数据
|
||||
byte[] buffer = new byte[8192];
|
||||
long remaining = length;
|
||||
int bytesRead;
|
||||
|
||||
while (remaining > 0 && (bytesRead = inputStream.read(buffer, 0, (int) Math.min(buffer.length, remaining))) != -1) {
|
||||
outputStream.write(buffer, 0, bytesRead);
|
||||
remaining -= bytesRead;
|
||||
}
|
||||
|
||||
outputStream.flush();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void checkFile(MultipartFile file, String code) {
|
||||
Assert.notBlank(code, "未指定文件配置");
|
||||
|
||||
@@ -13,9 +13,9 @@ import com.aliyun.oss.ClientException;
|
||||
import com.aliyun.oss.OSS;
|
||||
import com.aliyun.oss.OSSClientBuilder;
|
||||
import com.aliyun.oss.OSSException;
|
||||
import com.aliyun.oss.model.GetObjectRequest;
|
||||
import com.aliyun.oss.model.OSSObject;
|
||||
import com.newyetai.common.constant.CommonConstants;
|
||||
import com.newyetai.common.exception.BusinessException;
|
||||
import com.newyetai.common.exception.DevopsException;
|
||||
import com.newyetai.common.exception.util.Assert;
|
||||
import com.newyetai.common.util.EnvironmentUtils;
|
||||
@@ -120,4 +120,46 @@ public class AliFileStorage implements IFileStorage {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void downloadRange(String filePath, OutputStream outputStream, long start, long length) {
|
||||
try {
|
||||
// 创建GetObjectRequest并设置Range
|
||||
GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, dealPath(filePath));
|
||||
getObjectRequest.setRange(start, start + length - 1);
|
||||
|
||||
// 调用ossClient.getObject返回一个OSSObject实例
|
||||
OSSObject ossObject = ossClient.getObject(getObjectRequest);
|
||||
// 调用ossObject.getObjectContent获取文件输入流
|
||||
try (InputStream inputStream = ossObject.getObjectContent();) {
|
||||
// 使用更大的缓冲区提高性能
|
||||
byte[] buffer = new byte[64 * 1024]; // 64KB缓冲区
|
||||
long remaining = length;
|
||||
int bytesRead;
|
||||
|
||||
while (remaining > 0 && (bytesRead = inputStream.read(buffer, 0, (int) Math.min(buffer.length, remaining))) != -1) {
|
||||
outputStream.write(buffer, 0, bytesRead);
|
||||
remaining -= bytesRead;
|
||||
}
|
||||
|
||||
outputStream.flush();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} catch (OSSException oe) {
|
||||
log.info("Caught an OSSException, which means your request made it to OSS, "
|
||||
+ "but was rejected with an error response for some reason.");
|
||||
log.info("Error Message:" + oe.getErrorMessage());
|
||||
log.info("Error Code:" + oe.getErrorCode());
|
||||
log.info("Request ID:" + oe.getRequestId());
|
||||
log.info("Host ID:" + oe.getHostId());
|
||||
throw new DevopsException("oss请求异常" + oe.getMessage());
|
||||
} catch (ClientException ce) {
|
||||
log.info("Caught an ClientException, which means the client encountered "
|
||||
+ "a serious internal problem while trying to communicate with OSS, "
|
||||
+ "such as not being able to access the network.");
|
||||
log.info("Error Message:" + ce.getMessage());
|
||||
throw new DevopsException("oss客户端异常" + ce.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -55,4 +55,29 @@ public class LocalFileStorage implements IFileStorage {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void downloadRange(String filePath, OutputStream outputStream, long start, long length) {
|
||||
try (InputStream inputStream = this.download(filePath)) {
|
||||
// 跳过开始位置之前的字节
|
||||
long skipped = inputStream.skip(start);
|
||||
if (skipped != start) {
|
||||
log.warn("跳过字节数不匹配,期望: {}, 实际: {}", start, skipped);
|
||||
}
|
||||
|
||||
// 使用更大的缓冲区
|
||||
byte[] buffer = new byte[64 * 1024]; // 64KB缓冲区
|
||||
long remaining = length;
|
||||
int bytesRead;
|
||||
|
||||
while (remaining > 0 && (bytesRead = inputStream.read(buffer, 0, (int) Math.min(buffer.length, remaining))) != -1) {
|
||||
outputStream.write(buffer, 0, bytesRead);
|
||||
remaining -= bytesRead;
|
||||
}
|
||||
|
||||
outputStream.flush();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user