Nginx和Django下载* .mp3文件

时间:2018-05-16 16:28:02

标签: django nginx download

我有一个下载文件的Django项目,目前它在Linux VPS上托管,Nginx为整个项目提供服务。

当我尝试在此网址http://example.net/downloader/VYOjWnS4cMY/myfile.mp3

上下载文件时收到错误消息

这是我尝试下载文件时Nginx正在记录的错误。

2018/05/16 17:22:02 [error] 30075#30075: *3 open() "/var/www/html/project_folder/converter/media/myfile.mp3/downloader/VYOjWnS4cMY/myfile.mp3" failed (2: No such file or directory), client: 41.75.172.141, server: 173.212.212.165, request: "GET /downloader/VYOjWnS4cMY/myfile.mp3 HTTP/1.1", host: "www.example.com"

最后,这是我的Django视图方法,它处理下载功能。

def download(request, youtube_id, filename):

"""
Serves the audio file.
"""
filepath = os.path.join(settings.MEDIA_ROOT, filename)
file_exists = os.path.exists(filepath)

if settings.DEBUG:
    with open(filepath, 'rb') as file_data:
        response = HttpResponse(file_data.read(),
                                content_type='audio/mpeg')
    response['Content-Disposition'] = 'attachment; filename={}'.format(
        smart_str(filename))
    response['Content-Length'] = os.path.getsize(filepath)
    return response
else:
    # Have Nginx serve the file in production.
    response = HttpResponse(content_type='application/force-download')
    response['Content-Length'] = os.path.getsize(filepath)
    response['X-Accel-Redirect'] = os.path.join(settings.MEDIA_URL,
                                                smart_str(filename))
    return response

return HttpResponseRedirect(reverse('home'))

以下是我的nginx配置

 server {
     server_name example.com;

     location = /favicon.ico { access_log off; log_not_found off; }

     location /static/ {
        root /var/www/html/project_name/app_name;
    }
     location ~ ^.*/(?P<request_basename>[^/]+\.(mp3))$ {
        root /var/www/html/project_name/app_name/media/$request_basename/; 
      }

提前谢谢

2 个答案:

答案 0 :(得分:1)

问题在于你的nginx配置方式,你的位置块中的root应该指向root directory,从那里匹配整个相对路径。

我假设实际文件在此目录结构中: /var/www/html/project_folder/converter/media/downloader/VYOjWnS4cMY/myfile.mp3

如果是这样的话;将您的nginx位置块更改为:

 location ~ ^.*/(?P<request_basename>[^/]+\.(mp3))$ {
    root /var/www/html/project_folder/converter/media; 
  }

这将在我上面提到的路径中查找文件

更新1:

首先,看起来你的Nginx在它到达Django之前就劫持了这个请求 - 只是想让你知道你设置的路径将匹配,而Nginx将提供你所有的*.mp3 URI。看到你有Django代码来处理这个问题,你可能想在这里考虑预期的行为。

其次,在从您的评论中更好地理解问题之后,我很清楚问题是Nginx代码块再次出现。

您在评论中提到该文件位于/var/www/html/project_folder/converter/media/myfile.mp3

因此,您似乎建议的是,任何*.mp3文件,无论请求URI路径如何,都将从/media目录提供 - (如果是真的,我担心不好可扩展的设计)。

在这种情况下,您需要做的是在Nginx处重写URI,然后提供文件。

 location ~ ^.*/(?P<request_basename>[^/]+\.(mp3))$ {
    rewrite ^.*/(?P<request_basename>[^/]+\.(mp3))$ /$request_basename break;
    root /var/www/html/project_folder/converter/media; 
  }

为清楚起见:此重写块将获取其中包含.mp3的任何URL并重写它,以便直接从根目录提供该文件。 所有相对路径都将丢失

示例:

example.net/downloader/VYOjWnS4cMY/myfile.mp3 - &gt; /var/www/html/project_folder/converter/media/myfile.mp3

example.net/downloader/VYOjWnS4cMY/some_other_path/more_relative_paths/myotherfile.mp3 - &gt; /var/www/html/project_folder/converter/media/myotherfile.mp3

我希望这能给你足够的直觉来思考你需要达到的目标。

答案 1 :(得分:0)

首先确保文件位于路径 /var/www/html/project_folder/converter/media/myfile.mp3/downloader/VYOjWnS4cMY/myfile.mp3 中,如果是,那么错误可能与django回应。

作为一个好的做法,我建议文件下载应该由NGINX直接处理,而不是由django处理。 Webserver(s)NGINX / Apache善于处理它们。