Django + Gunicorn + Nginx + Python -> Link 从网络服务器下载文件

Django + Gunicorn + Nginx + Python -> Link to download file from webserver

在我的网页上,由 amazon-lightsail 在 nginx 和 gunicorn 后面托管的 Debian Web 服务器提供服务,用户可以发送请求以启动 Django 视图功能。此函数向后台进程添加一些工作,并每 5 秒检查一次后台进程是否创建了文件。如果文件存在,视图发送响应,用户可以下载文件。有时这个过程会花费很长时间,并且用户会收到 502 错误的网关消息。如果这个过程花费的时间太长,我喜欢向用户发送一封带有 link 的电子邮件,他可以在其中从 Web 服务器下载文件。我知道如何在该过程完成后发送电子邮件,但我不知道如何通过下载将文件提供给用户 link。

到此结束我的视图函数:

    print('######### Serve Downloadable File #########')
    while not os.path.exists(f'/srv/data/ship_notice/{user_token}'):
        print('wait on file is servable')
        time.sleep(5)
    
    # Open the file for reading content
    path = open(filepath, 'r')
    # Set the mime type
    mime_type, _ = mimetypes.guess_type(filepath)
    # Set the return value of the HttpResponse
    response = HttpResponse(path, content_type=mime_type)
    # Set the HTTP header for sending to browser
    response['Content-Disposition'] = f"attachment; filename={filename}" 
    # Return the response value
    return response

处理完成后向用户发送邮件的另一个模型函数:

def send_mail_precipitation(filepath, user_token, email):
    from django.core.mail import EmailMessage
    import time
    import os
    
    while not os.path.exists(f'/srv/data/ship_notice/{user_token}'):
        print('wait 30secs')
        time.sleep(30)
            
    msg = EmailMessage(
        subject = 'EnviAi data',
        body = 'The process is finished, you can download the file here.... ',
        to = [email]
    )
    msg.send()

文件太大,无法使用 msg.attach_file(文件路径)

发送

我有什么选择可以向用户发送 link 来下载这些文件。我是否需要设置 ftp server/folder,或者我有哪些选项?当我希望 link 只有 72 小时有效时,我必须做什么样的工作?非常感谢!

更新
一种方法是将文件复制到 public 可用的静态文件夹。我应该出于任何原因避免这种方法吗?

不是一个直接的答案,而是一个可行的方法。

这样的 long-running 任务通常使用 Celery 等附加工具来实现。让 view/api 端点 运行 只要它需要并保持请求进程等待直到完成是一种不好的做法。好的做法是尽可能快地做出回应。

你的情况是:

  • 创建一个 celery 任务来构建你的文件(创建任务很快)
  • return 响应中的任务 ID
  • 从具有给定任务 ID 的前端请求任务状态
  • 任务完成后文件 URL 应该 returned

也可以添加 任务完成后将执行的代码(由 Celery 自动启动)。您可以调用 email_user_when_file_is_ready 函数来响应此事件。

要使文件可下载,您可以在 nginx 配置中添加一个位置,就像您对静态和媒体文件夹所做的那样。将您的文件放到位置映射的文件夹中,仅此而已。让用户 URL 访问您的文件。