Range Requests Not Working as Expected with Dynamic API Source

Discussão em 'Angular' iniciado por FatimaHamieh, Março 18, 2025.

  1. FatimaHamieh

    FatimaHamieh Guest

    I'm implementing the range requests feature in ngx-extended-pdf-viewer to improve the loading performance of large PDF files.

    Setup & Expected Behavior

    I have added the following configuration in my Angular code:

    <ngx-extended-pdf-viewer #pdfViewer
    [src]="src"
    [useBrowserLocale]="true">

    pdfDefaultOptions.disableAutoFetch = true;
    pdfDefaultOptions.disableStream = false;
    pdfDefaultOptions.disableRange = false;


    When using a static file path, such as:

    this.src = '/assets/100MB-TESTFILE.pdf';


    The 100 MB file starts rendering after loading just 10 MB, with the remaining data fetched progressively.

    Issue

    However, when I use an API-generated file URL, such as:

    this.src = this.apiService.getDocumentFileURl();

    getDocumentFileURl() {
    return `${api_root}/document/${this.session.documentId}/version/${this.session.version}/view?language=${Helpers.getQueryParam('language', 'en')}&token=${this.session.token}`;
    }


    The PDF file is not displayed until 50 MB has been loaded, significantly increasing the loading time.

    Backend API Implementation

    The API responds to range requests using the following Java Jersey-based implementation:

    @GET
    @Produces(MediaType.APPLICATION_OCTET_STREAM)
    @Authorized
    @Path("view")
    public Response view(@QueryParam("language") String language, @Context ContainerRequestContext crc) throws Exception {
    try {
    String token = Token.getToken(crc);
    UserDocument userDocument = (UserDocument) crc.getProperty(UserDocument.USER_DOCUMENT_KEY);
    String filePath = userDocument.getVersion().getFileType() == FileType.VIDEO
    ? userDocument.getVersion().getFilePath()
    : userDocument.getVersion().getPDFCopyPath();

    if (!Files.exists(Paths.get(filePath))) {
    return Response.status(Status.NOT_FOUND).build();
    }

    InputStream fileStream = Helpers.getFileInputStreamForRead(filePath);
    long fileLength = fileStream.available();

    String rangeHeader = crc.getHeaderString("Range");

    if (rangeHeader != null && rangeHeader.startsWith("bytes=")) {
    // Parse Range Header
    String[] ranges = rangeHeader.substring("bytes=".length()).split("-");
    long start = Long.parseLong(ranges[0]);
    long end = ranges.length > 1 ? Long.parseLong(ranges[1]) : fileLength - 1;

    // Validate range
    if (start >= fileLength || end >= fileLength) {
    return Response.status(Response.Status.REQUESTED_RANGE_NOT_SATISFIABLE)
    .header("Content-Range", "bytes */" + fileLength)
    .build();
    }

    long contentLength = end - start + 1;
    fileStream.skip(start);

    return Response.status(Response.Status.PARTIAL_CONTENT)
    .entity(fileStream)
    .header("Access-Control-Expose-Headers", "Accept-Ranges")
    .header("Access-Control-Allow-Headers", "Accept-Ranges,range")
    .header("Content-Range", "bytes " + start + "-" + end + "/" + fileLength)
    .header("Accept-Ranges", "bytes")
    .header("Content-Length", contentLength)
    .header("Content-Type", "application/pdf; charset=UTF-8")
    .build();
    }

    // If no Range header, return the entire file
    return Response.ok()
    .header("Access-Control-Expose-Headers", "Accept-Ranges")
    .header("Access-Control-Allow-Headers", "Accept-Ranges,range")
    .header("Accept-Ranges", "bytes")
    .header("Content-Length", fileLength)
    .header("Content-Type", "application/pdf; charset=UTF-8")
    .entity(fileStream)
    .build();

    } catch (FileNotFoundException e) {
    e.printStackTrace();
    return Response.status(Response.Status.NOT_FOUND).build();
    }
    }


    Question

    How can I modify my implementation so that the dynamic API source behaves like the static source, allowing the PDF to load progressively after 10 MB, rather than requiring 50 MB before rendering begins?

    Any insights into how ngx-extended-pdf-viewer handles range requests dynamically would be greatly appreciated.

    Continue reading...

Compartilhe esta Página