Django - permission denied for text file created on the fly - python

I am trying to make a downloadable text file on the fly, i think i have achieved this but when i run the code i get a permission denied error.
also when i open this text file, does it get created anywhere in the file system? as i dont want to store these files, just create them and have them downloaded to users machine
IOError at /networks/configs/STR-RTR-01/7
[Errno 13] Permission denied: u'STR-CARD-RTR-01.txt'
config:
def configs(request, device, site_id):
site = get_object_or_404(ShowroomConfigData, pk=site_id)
config_template = get_object_or_404(ConfigTemplates, device_name=device)
file_name = device[:4] + site.location.upper()[:4] + "-" + device[4:] + ".txt"
device_config = None
with open(file_name, 'w') as config_file:
device_config = env.from_string(config_template.config)
device_config.stream(
STR = site.location.upper()[:4],
IP = site.subnet,
BGPASNO = site.bgp_as,
LOIP = site.r1_loopback_ip,
Location = site.location,
Date = site.opening_date,
).dump(config_file)
return render(request, file_name, {
})

If the goal is to provide a link where the user can download a file which is automatically generated, there's no need to write anything to disk.
You can just build the desired content in a Python string, and use the Content-Disposition header to suggest that a user's browser should download the file rather than display it, and its filename parameter to specify a default filename for the user to save the file as.
A slightly simpler example of a view function which does this...
from django.http import HttpResponse
def get_config_file(request):
filename = 'config.txt'
content = 'This is the content of my config file'
content_type = 'text/plain'
content_disposition = 'attachment; filename=%r' % filename
response = HttpResponse(content, content_type=content_type)
response['Content-Disposition'] = content_disposition
return response

Related

My download function saves a file with fixed name

I'm using Django 1.8 with Python 3.6.
When I use my download function below, it saves the file with a name fixed to local download directory. But I really want to keep the original name.
I can change the browser to open a download manager, but I want to know how to fix this filename to the original one.
def download(request):
path = "test.jpg" # Original filename that I intend to give.
file_path = os.path.join(settings.MEDIA_ROOT,path)
print("file_path :", file_path)
if os.path.exists(file_path):
readFile = open(file_path,"rb")
response = HttpResponse(readFile.read())
response['Content-Disposition'] ='attachment; filename'+os.path.basename(file_path)
response['Content-type'] = 'image/jpg'
return response
When I download the file, it is autosaved with a name 'Download.jpg', which is the browser's default directory name.
You have missed the =in your response['Content-Disposition'].
This one should work as expected:
response['Content-Disposition'] = 'attachment; filename=' + os.path.basename(file_path)

Serving pdf files by link, downloaded as pdf.html

Crated function to allow users download pdf files by link. Works fine, the only problem that what user save is .html. So all files are file.pdf.html.
def download(request,ticket_id):
ticket_path = str(Ticket.objects.get(id=ticket_id).upload)
with open('files/media/' + ticket_path, 'rb') as pdf:
response = HttpResponse(pdf.read())
response['content_type'] = 'application/pdf'
response['Content-Disposition'] = 'attachment;filename="file.pdf"'
return response
Why?
You should move content_type into HttpResponse(pdf.read(), content_type='application/pdf'), it's an attribute of HttpResponse

Django Serve .XLSX File and force download

I'm currently using openPYXL in order to open a template file within Django
module_dir = os.path.dirname(__file__) # get current directory
file_path = os.path.join(module_dir, fileName)
username = request.user.username
workbook = load_workbook(file_path)
worksheet = workbook.active
The file is then edited, and saved under a different name(This works fine, I can open the created file and it contains the information desired), however what I'm struggling with is serving this file to the user, I've tried various techniques such as shown below
workbook.save('EvalofSelf1.xlsx')
response = HttpResponse()
file_path = os.path.join(os.path.dirname(os.path.realpath(__name__)), 'EvalofSelf1.xlsx')
response['X-Sendfile'] = file_path
response['Content-Type'] = 'mimetype/submimetype'
response['Content-Disposition'] = 'attachment; filename=%s.xlsx' % 'DownloadedEval'
All of which serve a file as requested, but the file contains no actual data, is 0kb in size and unopenable, how can I serve up the created file from my Django project directory, retaining all information stored within it?
You're not ever putting the file contents into the response, so naturally it is 0 bytes. X-Sendfile is for a completely different purpose - when you're redirecting to a static server - and needs a URL, not a file path, anyway.
file_path = os.path.join(os.path.dirname(os.path.realpath(__name__)), 'EvalofSelf1.xlsx')
response = HttpResponse(open(file_path, 'rb').read())
response['Content-Type'] = 'mimetype/submimetype'
response['Content-Disposition'] = 'attachment; filename=DownloadedEval.xlsx'

Files Not Downloading Properly In Django/Nginx

I want users to be able to download file from my django web app. I wrote the below codes, but when I download a file, the file will turn into an error file. It won't open and the total size of the file would be 0 bytes.
Models:
class Emov(models.Model):
User=models.ForeignKey(User)
mov_file=models.FileField(upload_to='miiv')
mov_name=models.CharField(max_length=50)
email=models.EmailField() #email of the uploader
download_count=models.PositiveIntegerField(default=0)
#other fields follows
#property
def pretty_name(self):
return "{0}.{1}".format(slugify(self.title),
os.path.splitext(self.mov_name.name)[1])
Views:
def document_view(request,emov_id):
fileload=Emov.objects.get(id=emov_id)
response=HttpResponse()
response["Content-Disposition"]= "attachment; filename={0}".format(fileload.pretty_name)
response['X-Accel-Redirect']="/protected/{0}".format(fileload.mov_name.name)
return response
Nginx
location /protected/ {
internal;
root /C:/Python27/Scripts/env/Scripts/digi/media/miiv/;
}
What am I missing?
Try to do it like this:
fileload = Emov.objects.get(id=emov_id)
filename = fileload.mov_file.name.split('/')[-1]
response = HttpResponse(fileload.mov_file, content_type='text/plain') # your content type
response['Content-Disposition'] = 'attachment; filename=%s' % filename
return response
See:
https://docs.djangoproject.com/en/dev/ref/request-response/#telling-the-browser-to-treat-the-response-as-a-file-attachment
Hope it helps.
EDIT:
FileField.url attribute you should be able to pass a path to your files (like /protected/). https://docs.djangoproject.com/en/dev/ref/models/fields/#filefield-and-fieldfile

How can i make the common function/view for servinf downloadble files in django python

I am displaying the list of objects in the html table.
i have the download link in front of every row which i want them to download the linked file.
I have made this function
def make_downloadable_link(path):
#Prepare the form for downloading
wrapper = FileWrapper(open(mypath))
response = HttpResponse(wrapper,'application/pdf')
response['Content-Length'] = os.path.getsize(mypath)
fname = mypath.split('/')[-1]
response['Content-Disposition'] = 'attachment; filename= fname'
return response
This is working fine if i use it for hard coded path in view for single file. But i want to make a generic view so that it works on all the files in the table
I hav the path of the file avaiable in object.path variable but i am confused how can i pass the path object to the downlaod file view. because i want to hide that actual path from the user.
I don't know what to write in the URLs.py file fo that download file view
What would you like to do is get actual file path from object. And as you have said the file path is stored in object.path that makes it easy.
For example:
urls.py
url(r'^download/(?P<object_id>\d+)/$', "yourapp.views.make_downloadable_link", name="downloadable")
In views.py:
def make_downloadable_link(object_id):
# get object from object_id
object = ObjectModel.objects.get(id=object_id)
mypath = object.path
#prepare to serve the file
wrapper = FileWrapper(open(mypath))
response = HttpResponse(wrapper,'application/pdf')
response['Content-Length'] = os.path.getsize(mypath)
fname = mypath.split('/')[-1]
response['Content-Disposition'] = 'attachment; filename= fname'
return response

Categories