如何在Quarkus中使用Uni
和AsyncFile
来提供大文件的预览,例如,video/mp4
文件,同时从minio读取它?
我尝试使用Response
类来实现它,遵循this,但没有成功:
@GET
@Path("/download/{id}/ctx/{ctx}")
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response downloadFile(@PathParam("id") UUID fileId, @PathParam("ctx") String ctx, @QueryParam("preview") boolean preview,
@HeaderParam(value = "Range") String httpRangeList) {
try {
ResFile resFile = resFileService.getResFile(fileId, ctx);
String contentType = resFile.getMimeType();
Long size = resFile.getSize();
long rangeStart = 0;
long rangeEnd = size - 1;
if (preview) {
if (httpRangeList == null) {
return Response.status(Response.Status.OK)
.header("Access-Control-Expose-Headers", HttpHeaders.CONTENT_DISPOSITION)
.header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + resFileService.getResFile(fileId, ctx).getFileName() + "\"")
.header(HttpHeaders.CONTENT_TYPE, contentType)
.header("Accept-Ranges", "bytes")
.header("Content-Range", "bytes " + rangeStart + "-" + rangeEnd + "/" + size)
.header("Content-Length", String.valueOf(size))
.entity(resFileService.loadFileAsResourceRange(fileId, ctx, rangeStart, size)).build();
} else {
String[] ranges = httpRangeList.split("-");
rangeStart = Long.parseLong(ranges[0].substring(6));
if (ranges.length > 1) {
rangeEnd = Long.parseLong(ranges[1]);
} else {
rangeEnd = rangeStart + chunkSize;
}
rangeEnd = Math.min(rangeEnd, size - 1);
final byte[] data = resFileService.loadFileAsResourceRange(fileId, ctx, rangeStart, rangeEnd).readAllBytes();
log.info("data size: {}", data.length);
final String contentLength = String.valueOf((rangeEnd - rangeStart) + 1);
if (rangeEnd >= size) {
return Response.status(Response.Status.OK)
.header("Access-Control-Expose-Headers", HttpHeaders.CONTENT_DISPOSITION)
.header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + resFileService.getResFile(fileId, ctx).getFileName() + "\"")
.header(HttpHeaders.CONTENT_TYPE, contentType)
.header("Accept-Ranges", "bytes")
.header("Content-Range", "bytes " + rangeStart + "-" + rangeEnd + "/" + size)
.header("Content-Length", contentLength)
.entity(data).build();
}
else {
return Response.status(Response.Status.PARTIAL_CONTENT)
.header("Access-Control-Expose-Headers", HttpHeaders.CONTENT_DISPOSITION)
.header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + resFileService.getResFile(fileId, ctx).getFileName() + "\"")
.header(HttpHeaders.CONTENT_TYPE, contentType)
.header("Accept-Ranges", "bytes")
.header("Content-Range", "bytes " + rangeStart + "-" + rangeEnd + "/" + size)
.header("Content-Length", contentLength)
.entity(data).build();
}
}
} else {
return Response.status(Response.Status.OK)
.header("Access-Control-Expose-Headers", HttpHeaders.CONTENT_DISPOSITION)
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resFileService.getResFile(fileId, ctx).getFileName() + "\"")
.header(HttpHeaders.CONTENT_TYPE, contentType)
.entity(resFileService.loadFileAsResource(fileId, ctx)).build();
}
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(String.format(FILE_NOT_FOUND, fileId)).build();
} catch (IOException | MinIOException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(String.format(MINIO_EXCEPTION, e.getMessage())).build();
}
}
public InputStream loadFileAsResource(UUID uuid, String ctx) throws MinIOException, NotFoundException {
ResFile resFile = resFileRepository.findByResourceIdAndCtx(uuid, ctx).orElseThrow(() -> new NotFoundException(String.format(RESFILE_NOT_FOUND, uuid)));
return minIOService.downloadFile(Buckets.FILES.name().toLowerCase(), resFile.getPath());
}
public ByteArrayInputStream loadFileAsResourceRange(UUID fileId, String ctx, Long rangeStart, Long rangeEnd) throws MinIOException, NotFoundException, IOException {
ResFile resFile = resFileRepository.findByResourceIdAndCtx(fileId, ctx).orElseThrow(() -> new NotFoundException(String.format(RESFILE_NOT_FOUND, fileId)));
Files.copy(minIOService.downloadFile(Buckets.FILES.name().toLowerCase(), resFile.getPath()),
Paths.get("/tmp/" + resFile.getFileName()), StandardCopyOption.REPLACE_EXISTING);
return new ByteArrayInputStream(IOUtils.toByteArray(new FileInputStream("/tmp/" + resFile.getFileName())), rangeStart.intValue(), rangeEnd.intValue());
}
public InputStream downloadFile(String bucket, String filename) throws MinIOException {
try {
if(minioClient == null)
initializeMinIOClient();
// Get the object from bucket
return minioClient.getObject(GetObjectArgs.builder().bucket(bucket).object(filename).build());
} catch (Exception e) {
throw new MinIOException(String.format("Error occurred while downloading file '%s' | ", filename), e);
}
}
从this我读到了关于Uni
和AsyncFile
的内容。
但我不知道如何实施。
注意:我最好返回直接读取InputStream,而不保存从MinIO获取的文件
1条答案
按热度按时间fzwojiic1#
多亏了this
我能够用这种方法解决:
不需要
Uni
和AsyncFile
。