mirror of
https://github.com/gradio-app/gradio.git
synced 2025-04-06 12:30:29 +08:00
Open media type files in browser (#9151)
* changes * add changeset * changes * add changeset * changes * changes * changes * changes * changes * changes --------- Co-authored-by: Ali Abid <aliabid94@gmail.com> Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
This commit is contained in:
parent
675b50b2e5
commit
f1ef94a435
5
.changeset/legal-donkeys-accept.md
Normal file
5
.changeset/legal-donkeys-accept.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"gradio": patch
|
||||
---
|
||||
|
||||
fix:Open media type files in browser
|
@ -125,6 +125,17 @@ BUILD_PATH_LIB = cast(
|
||||
files("gradio").joinpath("templates", "frontend", "assets").as_posix(), # type: ignore
|
||||
)
|
||||
VERSION = get_package_version()
|
||||
XSS_VULNERABLE_EXTENSIONS = [
|
||||
".html",
|
||||
".htm",
|
||||
".js",
|
||||
".php",
|
||||
".asp",
|
||||
".aspx",
|
||||
".jsp",
|
||||
".xml",
|
||||
".svg",
|
||||
]
|
||||
|
||||
|
||||
class ORJSONResponse(JSONResponse):
|
||||
@ -530,7 +541,10 @@ class App(FastAPI):
|
||||
except PermissionError as err:
|
||||
raise HTTPException(status_code=400, detail=str(err)) from err
|
||||
rp_resp = await client.send(rp_req, stream=True)
|
||||
rp_resp.headers.update({"Content-Disposition": "attachment"})
|
||||
file_extension = os.path.splitext(url_path)[1].lower()
|
||||
if file_extension in XSS_VULNERABLE_EXTENSIONS:
|
||||
rp_resp.headers.update({"Content-Disposition": "attachment"})
|
||||
rp_resp.headers.update({"Content-Type": "application/octet-stream"})
|
||||
return StreamingResponse(
|
||||
rp_resp.aiter_raw(),
|
||||
status_code=rp_resp.status_code,
|
||||
@ -589,6 +603,16 @@ class App(FastAPI):
|
||||
if not abs_path.exists():
|
||||
raise HTTPException(404, f"File not found: {path_or_url}.")
|
||||
|
||||
mime_type, _ = mimetypes.guess_type(abs_path)
|
||||
file_extension = os.path.splitext(abs_path)[1].lower()
|
||||
|
||||
if file_extension in XSS_VULNERABLE_EXTENSIONS:
|
||||
media_type = "application/octet-stream"
|
||||
content_disposition_type = "attachment"
|
||||
else:
|
||||
media_type = mime_type or "application/octet-stream"
|
||||
content_disposition_type = "inline"
|
||||
|
||||
range_val = request.headers.get("Range", "").strip()
|
||||
if range_val.startswith("bytes=") and "-" in range_val:
|
||||
range_val = range_val[6:]
|
||||
@ -597,7 +621,8 @@ class App(FastAPI):
|
||||
start = int(start)
|
||||
end = int(end)
|
||||
headers = dict(request.headers)
|
||||
headers["Content-Disposition"] = "attachment"
|
||||
headers["Content-Disposition"] = content_disposition_type
|
||||
headers["Content-Type"] = media_type
|
||||
response = ranged_response.RangedFileResponse(
|
||||
abs_path,
|
||||
ranged_response.OpenRange(start, end),
|
||||
@ -609,8 +634,9 @@ class App(FastAPI):
|
||||
return FileResponse(
|
||||
abs_path,
|
||||
headers={"Accept-Ranges": "bytes"},
|
||||
content_disposition_type="attachment",
|
||||
media_type="application/octet-stream",
|
||||
content_disposition_type=content_disposition_type,
|
||||
media_type=media_type,
|
||||
filename=abs_path.name,
|
||||
)
|
||||
|
||||
@app.get(
|
||||
|
@ -254,6 +254,33 @@ class TestRoutes:
|
||||
assert len(file_response.text) == len(media_data.BASE64_IMAGE)
|
||||
io.close()
|
||||
|
||||
def test_response_attachment_format(self):
|
||||
image_file = tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".png")
|
||||
image_file.write(media_data.BASE64_IMAGE)
|
||||
image_file.flush()
|
||||
|
||||
html_file = tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".html")
|
||||
html_file.write("<html>Hello, world!</html>")
|
||||
html_file.flush()
|
||||
|
||||
io = gr.Interface(lambda s: s.name, gr.File(), gr.File())
|
||||
app, _, _ = io.launch(
|
||||
prevent_thread_lock=True,
|
||||
allowed_paths=[
|
||||
os.path.dirname(image_file.name),
|
||||
os.path.dirname(html_file.name),
|
||||
],
|
||||
)
|
||||
client = TestClient(app)
|
||||
|
||||
file_response = client.get(f"/file={image_file.name}")
|
||||
assert file_response.headers["Content-Type"] == "image/png"
|
||||
assert "inline" in file_response.headers["Content-Disposition"]
|
||||
|
||||
file_response = client.get(f"/file={html_file.name}")
|
||||
assert file_response.headers["Content-Type"] == "application/octet-stream"
|
||||
assert "attachment" in file_response.headers["Content-Disposition"]
|
||||
|
||||
def test_allowed_and_blocked_paths(self):
|
||||
with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as tmp_file:
|
||||
io = gr.Interface(lambda s: s.name, gr.File(), gr.File())
|
||||
|
Loading…
x
Reference in New Issue
Block a user