I have a Django app with fastCGI.
The following view starts lots of proccesses named "/usr/bin/python index.fcgi". They suddenly appear and just stay there forever.
def serveMusicFile(request,filename):
from django.conf import settings
file = open('/my/private/file/location/'+filename)
response = HttpResponse(file.read(), mimetype="audio/mpeg")
response['Accept-Ranges'] = 'bytes'
response['Content-Length'] = os.path.getsize('/my/private/file/location/'+filename)
response['Content-Disposition'] = 'filename='+filename
return response
So, why does Django/fastCGI start this proccess? How can I stop them being pilled?
Related
I've written a Django app which I'm trying to get set up on shared web hosting (A2). It's working, except that when I go to:
http://example.com/terms/
the URL changes in the browser bar to:
http://example.com/home/myusername/myappfolder/myappname/terms/
showing the full path to where my app is on disk.
This doesn't happen with static files - e.g. http://example.com.com/static/image.png works normally.
The app is running in a virtual environment. I'm using python 3.6.8 and Django 2.1.4.
I followed these instructions to set up my app, which include setting up this passenger.wsgi file, that looks like this:
import myapp.wsgi
SCRIPT_NAME = '/home/username/myapp'
class PassengerPathInfoFix(object):
"""
Sets PATH_INFO from REQUEST_URI because Passenger doesn't provide it.
"""
def __init__(self, app):
self.app = app
def __call__(self, environ, start_response):
from urllib.parse import unquote
environ['SCRIPT_NAME'] = SCRIPT_NAME
request_uri = unquote(environ['REQUEST_URI'])
script_name = unquote(environ.get('SCRIPT_NAME', ''))
offset = request_uri.startswith(script_name) and len(environ['SCRIPT_NAME']) or 0
environ['PATH_INFO'] = request_uri[offset:].split('?', 1)[0]
return self.app(environ, start_response)
application = myapp.wsgi.application
application = PassengerPathInfoFix(application)
I'd be grateful for any pointers as to where to look to solve this.
Got it working!
In my modified passenger_wsgi.py, I changed the line
SCRIPT_NAME = os.getcwd()
to
SCRIPT_NAME = ''
One thing I should point out is that the absolute path was getting inserted on redirects - so if I visited
http://example.com/terms
it would redirect to
http://example.com/terms/
and insert the path in the URL.
As you're debugging I recommend disabling the cache, as that threw me for several loops when changes I made didn't seem to take effect.
Thanks to this question for getting me on the right track.
This is my views.py files:
from django.http import HttpResponse
def render(request):
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="somefilename.pdf"'
response['X-Sendfile'] = '/files/filename.pdf'
# path relative to views.py
return response
When I run the server and request
http://localhost:8080/somestring
I get an empty file called somefilename.pdf. I suspect that there is some crucial part missing in render.
The other parts of this app outside of views.py are correct to my understanding.
Here is the code that solved my problem:
from django.http import HttpResponse
from wsgiref.util import FileWrapper
def render(request):
response = HttpResponse(FileWrapper(open('file.pdf', 'rb')), content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="somefilename.pdf"'
return response
The manage.py runserver development serer doesn't support X-Sendfile. In production, you need to enable X-Sendfile for your server (e.g. Apache).
You may find the django-sendfile package useful. It has a backend that you can use in development. However, it hasn't had a release in some time, and I found that I had to apply pull request 62 to get Python 3 support.
I want to download zip files using Django views. I have gone through many solutions in stack overflow. But the file does not get downloaded at all. Here is the code I am using.
Could anyone, tell me where I am going wrong.
response = HttpResponse(mimetype='application/zip')
response['Content-Disposition'] = 'attachment; filename=%s' % doc[Zip_file_name]
response['X-Sendfile'] = "./Zipfiles" # the path where the zip files are stored
return response
In chrome, If I use inspect element, and double click on the url shown in the network tab, the file gets downloaded as it is recognized as a http get request, whereas on button click nothing happens.
Please Help.
from django.http import HttpResponse
from django.core.servers.basehttp import FileWrapper
# file
response = HttpResponse(FileWrapper(myfile), content_type='application/zip')
response['Content-Disposition'] = 'attachment; filename=myfile.zip'
return response
In a view I create new file with:
sys.stdout = open(backup_name, 'w')
call_command('dumpdata')
How can I now return this file to user?
I tried to change mimetype in HttpResponse to 'application/json' but how can I add file content to response?
Or maybe there is other way to return file?
.
I know it's a bit late, but I found this a useful starting point so I thought others could benefit from what I found too.
For a small file, if you place the json file in a template folder, django can find it and you can return it with render_to_response:
return render_to_response(data_file,mimetype='application/json')
I found this to be problematic for large datasets on certain browsers. I would get the error An existing connection was forcibly closed by the remote host. An alternative approach fixed this.
First you must create full path to your file. Use the PROJECT_ROOT variable (defined by PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__)) in settings.py). To access this and the os methods you must import settings, os in views.py. Once you have this file location you can return it using the code below:
backup_path = os.path.join(settings.PROJECT_ROOT, "templates", "json_dumps", "large_file.json")
return HttpResponse(open(backup_path, 'r'),content_type = 'application/json; charset=utf8')
I found this worked well for even very large files.
OK I have it:
response = HttpResponse(open(backup_path, "r"), mimetype='application/json', )
response['Content-Disposition'] = "filename=%s" % backup_name"
After saving file on disc I open it for reading and set file name in response.
Anyone has another idea?
I was trying to return a dictionary as a json file. Here is my solution:
import json
import cStringIO as StringIO
from wsgiref.util import FileWrapper
from django.http import HttpResponse
data_string = json.dumps(data)
json_file = StringIO.StringIO()
json_file.write(data_string)
json_file.seek(0)
wrapper = FileWrapper(json_file)
response = HttpResponse(wrapper, content_type='application/json')
response['Content-Disposition'] = 'attachement; filename=dump.json'
return response
Just copy/link/call the dumpdata code related to model serialization, and dump it directly into the response, so you avoid permission problems and filesystem pollution. Content-disposition and mimetype still applies.
Remember anyway that dumpdata can be a lenghty process, so you are exposed to timeouts.
My final solution is (thanks to saverio):
response = HttpResponse(mimetype='application/json', )
response['Content-Disposition'] = "filename=%s" % backup_name
sys.stdout = response
call_command('dumpdata')
I need to return css files and js files according to specific logic. Clearly, static serve does not perform what I need. I have a view, whose render method uses logic to find the proper file, but then I have to return it. Technically, I can just read the file and stuff it into a HttpResponse object with the proper mime type, but I was wondering if there was a better strategy. (like fpassthru() in php)
This is what I used:
test_file = open('/home/poop/serve/test.pdf', 'rb')
response = HttpResponse(content=test_file)
response['Content-Type'] = 'application/pdf'
response['Content-Disposition'] = 'attachment; filename="%s.pdf"' \
% 'whatever'
return response
What webserver software are you using?
At least for Apache and NginX, there is a module enabling you to use the X-SendFile HTTP header. The NginX website says Lighty can do this, too.
In your wrapper view:
...
abspath = '/most_secret_directory_on_the_whole_filesystem/protected_filename.css'
response = HttpResponse()
response['X-Sendfile'] = abspath
response['Content-Type'] = 'mimetype/submimetype'
# or let your webserver auto-inject such a header field
# after auto-recognition of mimetype based on filename extension
response['Content-Length'] = <filesize>
# can probably be left out if you don't want to hassle with getting it off disk.
# oh, and:
# if the file is stored via a models.FileField, you just need myfilefield.size
response['Content-Disposition'] = 'attachment; filename=%s.css' \
% 'whatever_public_filename_you_need_it_to_be'
return response
Then you can connect the view via http://mysite.com/url_path/to/serve_hidden_css_file/.
You can use it anytime you need to do something upon a file being requested that should not be directly accessible to users, like limiting who can access it, or counting requests to it for stats, or whatever.
For Apache: http://tn123.ath.cx/mod_xsendfile/
For NginX: http://wiki.nginx.org/NginxXSendfile
Why don't you use Django staticfiles inside your view
from django.contrib.staticfiles.views import serve
...
def view_function(request):
return serve(request, 'absolute_path_to_file_name')
Why not return an HttpResponseRedirect to the location of the correct static file?
Serving files directly from a view is very slow. If you are looking for normal file serving see this question: Having Django serve downloadable files
To very easily serve files through a view (for debug purposes, for example) keep reading.
# In your urls.py:
url(r'^test-files/(?P<name>.+)/$', views.test_files, name='test_files'),
# In your views.py:
from django.http.response import HttpResponse
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt # (Allows file download with POST requests, can be omitted)
def test_files(request, name):
if name == "myxml":
fsock = open("/djangopath/data/static/files/my.xml", "rb")
return HttpResponse(fsock)
This allows you to download the file from: http://127.0.0.1:8080/app/test-files/myxml/
Pass an iterator (such as the result of open()) to the HttpResponse constructor.
you can use below code in your view:
Note:in this function I return images but you can return every thing based your need and set your context_type
from django.http import HttpResponse,Http404
import os
def img_finder(request, img_name):
try:
with open(os.path.dirname(os.path.abspath(__file__)) + '/static/img/' + img_name, 'rb') as f:
return HttpResponse(f.read(), content_type="image/jpeg")
except IOError:
raise Http404
Here the most simple and efficient way to do this.
app/urls.py
from django.urls import re_path
from app import views
urlpatterns = [
re_path(r'^(?P<public_url>.*)$', views.public, name="public"),
]
Warning : put the URL pattern at the end
app/views.py
import os
from django.conf import settings
from django.views.static import serve
def public(request, public_url):
public_folder = os.path.join(str(settings.BASE_DIR), 'folder_path')
return serve(request, public_url, document_root=public_folder)
It should be wasteful to use django to serve static content (not to mention, several orders of magnitude slower).
I'd rather convert the view into a context processor and use the variables in templates to find what blocks to include.