我有一个下载文件的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/;
}
提前谢谢
答案 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;
}
这将在我上面提到的路径中查找文件
首先,看起来你的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善于处理它们。