-
-
Notifications
You must be signed in to change notification settings - Fork 901
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
View first page before entire document is loaded - support range header #419
Comments
Hi, It seems like the easiest way to get the behavior you want is to simply pass an URL as |
Thanks for the reply (and the awesome library, for that matter) @wojtekmaj! Unfortunately, I do pass the URL as a file prop (source, demo), but it only renders after the entire document has been fetched. Also, the request for the PDF file does not appear have any range headers. Perhaps this conditional is never actually true if I pass a string?
|
According to PDF.js developers, PDF.js does not support <Document
options={{
httpHeaders: {
'Accept-Encoding': 'Identity',
}
}}
file={"https://example.com/some.pdf"}
> However, it does not, so I'm still investigating what is going on. It seems likely that it's a pdf.js issue. |
@joepio Did you manage to solve this issue? I am using I have tried passing to |
@angel-langdon never managed to get it working, unfortunately... |
@joepio Well I finally managed to do it, it was failing because our backend implementation was not compatible with Frontend componentinterface MemoizedDocumentProps {
url: string;
children: JSX.Element | null;
}
const MemoizedDocument = memo((props: MemoizedDocumentProps) => {
const file = useMemo(
() => ({ url: props.url }),
[props.url]
);
return (
<Document
file={file}
>
{props.children}
</Document>
);
}); Backend implementation (in Python)import os
from typing import BinaryIO
from fastapi import FastAPI, HTTPException, Request, status
from fastapi.responses import StreamingResponse
def send_bytes_range_requests(
file_obj: BinaryIO, start: int, end: int, chunk_size: int = 10_000
):
"""Send a file in chunks using Range Requests specification RFC7233
`start` and `end` parameters are inclusive due to specification
"""
with file_obj as f:
f.seek(start)
while (pos := f.tell()) <= end:
read_size = min(chunk_size, end + 1 - pos)
yield f.read(read_size)
def _get_range_header(range_header: str, file_size: int) -> tuple[int, int]:
def _invalid_range():
return HTTPException(
status.HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE,
detail=f"Invalid request range (Range:{range_header!r})",
)
try:
h = range_header.replace("bytes=", "").split("-")
start = int(h[0]) if h[0] != "" else 0
end = int(h[1]) if h[1] != "" else file_size - 1
except ValueError:
raise _invalid_range()
if start > end or start < 0 or end > file_size - 1:
raise _invalid_range()
return start, end
def range_requests_response(
request: Request, file_path: str, content_type: str
):
"""Returns StreamingResponse using Range Requests of a given file"""
file_size = os.stat(file_path).st_size
range_header = request.headers.get("range")
headers = {
"content-type": content_type,
"accept-ranges": "bytes",
"content-encoding": "identity",
"content-length": str(file_size),
"access-control-expose-headers": (
"content-type, accept-ranges, content-length, "
"content-range, content-encoding"
),
}
start = 0
end = file_size - 1
status_code = status.HTTP_200_OK
if range_header is not None:
start, end = _get_range_header(range_header, file_size)
size = end - start + 1
headers["content-length"] = str(size)
headers["content-range"] = f"bytes {start}-{end}/{file_size}"
status_code = status.HTTP_206_PARTIAL_CONTENT
return StreamingResponse(
send_bytes_range_requests(open(file_path, mode="rb"), start, end),
headers=headers,
status_code=status_code,
)
app = FastAPI()
@app.get("/video")
def get_video(request: Request):
return range_requests_response(
request, file_path="path_to_my_video.mp4", content_type="video/mp4"
) I would strongly recommend reading the Range Requests RFC https://datatracker.ietf.org/doc/html/rfc7233 to understand everything, there are a few gotchas |
hello, Are you write like this ? |
@bolosea I don't know if not english characters are valid, see my updated answer for full details |
thanks for your reply,but I don't backend。 and I found that url ' https://s3.amazonaws.com/pdftron/downloads/pl/2gb-sample-file.pdf' in pdf.js example project can works as expected in this |
This issue is stale because it has been open 90 days with no activity. Remove stale label or comment or this issue will be closed in 14 days. |
This issue was closed because it has been stalled for 14 days with no activity. |
Before you start - checklist
What are you trying to achieve? Please describe.
In our project (issue, demo), I'd like to load only the pages that I'm viewing, and render the first page before the entire document is loaded.
From my understanding, PDF.js supports Range headers and the
react-pdf
API describes that it's possible to include aPDFDataRangeTransport
object in thefile
property. I fail to see what to do to actually send these Range headers, though!Describe solutions you've tried
Environment
The text was updated successfully, but these errors were encountered: