表单提交上的 Django 动态文件输出在移动设备上不起作用
Django dynamic file output on form submit doesn't work on mobile
我正在尝试通过写入 io.BytesIO 来输出文件,并在表单作为文件附件提交时发送。 Linux 上的 Firefox 一切正常,但移动浏览器在浏览器接受下载时发送 GET 请求,并将 HTTP 响应保存为下载的文件。
这是我的视图函数:
from django.views.decorators.csrf import csrf_exempt
from django.http import FileResponse, HttpResponse
import io
@csrf_exempt
def download_file(request):
if request.method == 'POST':
buffer = io.BytesIO()
buffer.write('Text file content'.encode('UTF-8'))
buffer.seek(0)
return FileResponse(buffer, as_attachment=True, filename='file.txt')
return HttpResponse('<form method="post"><button>Download</button></form>')
这是在 Linux 上从 Firefox 提交表单时日志的样子:
[20/Sep/2020 18:15:31] "POST /test/ HTTP/1.1" 200 17
Linux 上的下载文件:
Text file content
这是在 Android 上从 Firefox 提交表单时日志的样子:
[20/Sep/2020 18:16:47] "POST /test/ HTTP/1.1" 200 17
[20/Sep/2020 18:16:48] "GET /test/ HTTP/1.1" 200 52
Android 上的下载文件:
<form method="post"><button>Download</button></form>
我正在使用 Python 3.8.5 和 Django 3.1.1。
解决方案
考虑使用具有适当内容类型和内容配置的 HttpResponse 或 StreamingHttpResponse。
例子
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
import io
@csrf_exempt
def download_file(request):
if request.method == 'POST':
buffer = io.BytesIO()
buffer.write('Text file content'.encode('UTF-8'))
buffer.seek(0)
response = HttpResponse(buffer, content_type='text/plain')
response['Content-Disposition'] = 'attachment; filename=file.txt'
return response
return HttpResponse('<form method="post"><button>Download</button></form>')
参考资料
StreamingHttpResponse:https://docs.djangoproject.com/en/3.1/ref/request-response/#django.http.StreamingHttpResponse
问题
在 Firefox android 应用程序中,应用程序在 确认下载 操作后发送 HTTP GET 请求。您可以看到相同的服务器日志(在 OP 中也是如此)
解决方法是什么?
不推荐使用 HTTP POST 方法下载文件,请改用 HTTP GET(参考:)。因此,相应地更改您的视图以下载文件。
def sample_view(request):
buffer = io.BytesIO()
buffer.write('Text file content'.encode('UTF-8'))
buffer.seek(0)
return FileResponse(buffer, as_attachment=True, filename='file.txt')
我正在尝试通过写入 io.BytesIO 来输出文件,并在表单作为文件附件提交时发送。 Linux 上的 Firefox 一切正常,但移动浏览器在浏览器接受下载时发送 GET 请求,并将 HTTP 响应保存为下载的文件。
这是我的视图函数:
from django.views.decorators.csrf import csrf_exempt
from django.http import FileResponse, HttpResponse
import io
@csrf_exempt
def download_file(request):
if request.method == 'POST':
buffer = io.BytesIO()
buffer.write('Text file content'.encode('UTF-8'))
buffer.seek(0)
return FileResponse(buffer, as_attachment=True, filename='file.txt')
return HttpResponse('<form method="post"><button>Download</button></form>')
这是在 Linux 上从 Firefox 提交表单时日志的样子:
[20/Sep/2020 18:15:31] "POST /test/ HTTP/1.1" 200 17
Linux 上的下载文件:
Text file content
这是在 Android 上从 Firefox 提交表单时日志的样子:
[20/Sep/2020 18:16:47] "POST /test/ HTTP/1.1" 200 17
[20/Sep/2020 18:16:48] "GET /test/ HTTP/1.1" 200 52
Android 上的下载文件:
<form method="post"><button>Download</button></form>
我正在使用 Python 3.8.5 和 Django 3.1.1。
解决方案
考虑使用具有适当内容类型和内容配置的 HttpResponse 或 StreamingHttpResponse。
例子
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
import io
@csrf_exempt
def download_file(request):
if request.method == 'POST':
buffer = io.BytesIO()
buffer.write('Text file content'.encode('UTF-8'))
buffer.seek(0)
response = HttpResponse(buffer, content_type='text/plain')
response['Content-Disposition'] = 'attachment; filename=file.txt'
return response
return HttpResponse('<form method="post"><button>Download</button></form>')
参考资料
StreamingHttpResponse:https://docs.djangoproject.com/en/3.1/ref/request-response/#django.http.StreamingHttpResponse
问题
在 Firefox android 应用程序中,应用程序在 确认下载 操作后发送 HTTP GET 请求。您可以看到相同的服务器日志(在 OP 中也是如此)
解决方法是什么?
不推荐使用 HTTP POST 方法下载文件,请改用 HTTP GET(参考:)。因此,相应地更改您的视图以下载文件。
def sample_view(request):
buffer = io.BytesIO()
buffer.write('Text file content'.encode('UTF-8'))
buffer.seek(0)
return FileResponse(buffer, as_attachment=True, filename='file.txt')