fix: Make Content-Disposition header RFC 2183 compliant

Changes all Content-Disposition headers from:
  filename="name.ext"
to:
  attachment; filename="name.ext"

This ensures compatibility with RFC 2183 and allows third-party
downloading libraries (e.g., Go's mime.ParseMediaType) to correctly
parse the filename.

Fixes #8914
This commit is contained in:
andygoodluck 2026-02-14 09:49:34 +08:00
parent 726af73867
commit 491372b827
2 changed files with 53 additions and 4 deletions

View File

@ -521,7 +521,7 @@ class PromptServer():
buffer.seek(0)
return web.Response(body=buffer.read(), content_type=f'image/{image_format}',
headers={"Content-Disposition": f"filename=\"{filename}\""})
headers={"Content-Disposition": f"attachment; filename=\"{filename}\""})
if 'channel' not in request.rel_url.query:
channel = 'rgba'
@ -541,7 +541,7 @@ class PromptServer():
buffer.seek(0)
return web.Response(body=buffer.read(), content_type='image/png',
headers={"Content-Disposition": f"filename=\"{filename}\""})
headers={"Content-Disposition": f"attachment; filename=\"{filename}\""})
elif channel == 'a':
with Image.open(file) as img:
@ -558,7 +558,7 @@ class PromptServer():
alpha_buffer.seek(0)
return web.Response(body=alpha_buffer.read(), content_type='image/png',
headers={"Content-Disposition": f"filename=\"{filename}\""})
headers={"Content-Disposition": f"attachment; filename=\"{filename}\""})
else:
# Get content type from mimetype, defaulting to 'application/octet-stream'
content_type = mimetypes.guess_type(filename)[0] or 'application/octet-stream'
@ -570,7 +570,7 @@ class PromptServer():
return web.FileResponse(
file,
headers={
"Content-Disposition": f"filename=\"{filename}\"",
"Content-Disposition": f"attachment; filename=\"{filename}\"",
"Content-Type": content_type
}
)

49
test_rfc2183_fix.py Normal file
View File

@ -0,0 +1,49 @@
#!/usr/bin/env python3
"""
Test for Content-Disposition header fix
Verifies that the header matches RFC 2183 format
"""
import re
def test_content_disposition_header():
"""Test that Content-Disposition header is RFC 2183 compliant"""
# Read the server.py file
with open('server.py', 'r') as f:
content = f.read()
# Find all Content-Disposition headers
pattern = r'"Content-Disposition":\s*f"([^"]+)"'
matches = re.findall(pattern, content)
print(f"Found {len(matches)} Content-Disposition headers")
all_pass = True
for i, match in enumerate(matches, 1):
print(f"\nHeader {i}: {match}")
# Check RFC 2183 compliance
# Should start with "attachment;" or "inline;" followed by filename
if match.startswith("attachment;") and "filename=" in match:
print(f" ✅ RFC 2183 compliant (attachment disposition)")
elif match.startswith("inline;") and "filename=" in match:
print(f" ✅ RFC 2183 compliant (inline disposition)")
elif match.startswith("filename="):
print(f" ❌ NOT RFC 2183 compliant (missing disposition type)")
all_pass = False
else:
print(f" ⚠️ Unknown format")
print("\n" + "="*50)
if all_pass:
print("✅ All headers are RFC 2183 compliant!")
else:
print("❌ Some headers are NOT RFC 2183 compliant!")
return all_pass
if __name__ == "__main__":
import sys
success = test_content_disposition_header()
sys.exit(0 if success else 1)