Map physical path of a file to serve path for download - python

In my AngularJS/Python app, I uploaded a file using dropzone which has a physical path of something like this:
D:\uploadedFiles\tmpmj02zkex___5526310795850751687_n.jpg'
Now I want to create a link for this file for display and download on the front end. A link that looks something like this:
http://127.0.0.1:8000/uploadedFiles/tmpmj02zkex___5526310795850751687_n.jpg
What is the best way to achieve this?

You can simply add a url pattern in eg. urls.py:
from django.conf.urls import url
from . import views
urlpatterns = [
...,
url(r'^uploadedFiles/(?P<file_name>.+)/$', views.download, name='download')
]
and a download method in the controller in eg. views.py as suggested in here:
import os
from django.conf import settings
from django.http import HttpResponse
# path to the upload dir
UPLOAD_DIR = 'D:\uploadedFiles'
...
def download(request, file_name):
file_path = os.path.join(UPLOAD_DIR, file_name)
if os.path.exists(file_path):
with open(file_path, 'rb') as fh:
response = HttpResponse(fh.read(), content_type="application/octet-stream")
response['Content-Disposition'] = 'attachment; filename=' + os.path.basename(file_path)
return response
else:
raise Http404

Related

How to let users download an excel file in a specific path in Django?

I am a beginner in Python Django. I am trying to let users download an excel file in a specific path in Django.
My views.py is as follows. As you can see, I want to let user download OOOO.xlsx in the path /mysite/upload/.
def download_file(request):
# Define Django project base directory
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Define file name
filename = 'OOOO.xlsx'
# Define the full file path
filepath = BASE_DIR + '/mysite/upload/' + filename
# 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'] = "attachment; filename=%s" % filename
# Return the response value
return response
My urls.py is as follows.
urlpatterns = [
path('admin/', admin.site.urls),
path('',views.index),
path('download/', views.download_file),
]
However, it keeps showing an error like this on my HTML page.
<>
Please help me to find the bug.
You should use djangos FileResponse. Read here for more.
def download_file(request):
# Define Django project base directory
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Define file name
filename = 'OOOO.xlsx'
# Define the full file path
filepath = BASE_DIR + '/mysite/upload/' + filename
return FileResponse(open(filepath, 'rb'), as_attachment=True)

Django MEDIA not accessible

My Django app is unable to see MEDIA directory. When I run one of my views I need to open a file. The scenario is to:
take a record with requested id from data base
get the file path to a file
send the file to external server for OCR purposes
urls.py
from django.conf.urls.static import static
urlpatterns = [
#my urls
] + static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
models.py
from django.db import models
from django.contrib.auth.models import User
class Homework( models.Model):
title = models.CharField(max_length = 200, default = None)
image = models.FileField(upload_to='user_scans/')
author = models.ForeignKey(User, default=None, on_delete = models.CASCADE)
latex = models.TextField(default = "No LaTeX Here")
settings.py:
from pathlib import Path
from django.conf.urls.static import static
BASE_DIR = Path(__file__).resolve().parent.parent
...
DEBUG = True
...
STATIC_ROOT = BASE_DIR / 'static'
STATIC_URL = '/static/'
MEDIA_ROOT = BASE_DIR / 'media'
MEDIA_URL = "/media/"
views.py
import requests
import json
from django.shortcuts import render, get_object_or_404
from .models import Homework
def create_homework(request):
if request.method == 'GET':
#some GET stuff
if request.method == 'POST':
homework = Homework()
homework.title = title
homework.image = image
homework.author = author
homework.save()
id = homework.id
json_to_mathsnip(id)
....
def json_to_mathsnip(id):
homework = get_object_or_404(Homework, pk=id)
f = open(homework.image.url, "rb")
...
some later stuff
...
Unfortunately I'm constantly running into an error:
FileNotFoundError at /homework/new
[Errno 2] No such file or directory: '/media/user_scans/kwa.png'
My main concern is I can access file from localhost:8000/media/user_scans/kwa.png
and from admin panel. Requested file is saved properly:
Also settings.py configuration seems to be in tact. What might be the issue?
(env) $ pip freeze
asgiref==3.5.0
backports.zoneinfo==0.2.1
certifi==2021.10.8
charset-normalizer==2.0.12
Django==4.0.1
idna==3.3
Pillow==9.0.0
psycopg2-binary==2.9.3
requests==2.27.1
sqlparse==0.4.2
urllib3==1.26.9
This may not be the best way, but I tried it and it works. The bottom line is that when using the open() function with a relative path, such as /media/user_scans/kwa.png, then that file must be in the same directory as where the function is called. You could just find the absolute path of your image files in your computer, then append the filename to that and it will work, or you can do what I have below.
import requests
import json
from django.shortcuts import render, get_object_or_404
from .models import Homework
# ADD THESE
import os
from pathlib import Path
def create_homework(request):
if request.method == 'GET':
#some GET stuff
if request.method == 'POST':
homework = Homework()
homework.title = title
homework.image = image
homework.author = author
homework.save()
id = homework.id
json_to_mathsnip(id)
....
def json_to_mathsnip(id):
homework = get_object_or_404(Homework, pk=id)
# ADD THESE
BASE_DIR = Path(__file__).resolve().parent.parent
path_to_image_file = str(BASE_DIR) + homework.image.url
f = open(path_to_image_file, "rb")
...
some later stuff
...
When you show an image in Django, or you access its url, it is a relative path, but the root is the url root, localhost:8000/, and the image url is appended to that, and Django manages to find the file (how exactly, I don't know). But the image file is in your computer, and that is what you want to open.

Django how to change where uploaded file is saved

After uploading a CSV file into a Django form and submitting, Django creates a copy of this in the project app folder. I want to be able to tell Django to store this copy in another directory. How do I do that? Thanks.
You can do something like that :
models.FileField( upload_to="YourFolder")
In your setting your can specify the folder media :
Media URL
MEDIA_URL = "/media/"
Documentation for the FileField
If you want to specify the folder at save time :
from django.shortcuts import render
from django.conf import settings
from django.core.files.storage import FileSystemStorage
def upload(request):
folder='my_folder/'
if request.method == 'POST' and request.FILES['myfile']:
myfile = request.FILES['myfile']
fs = FileSystemStorage(location=folder) #defaults to MEDIA_ROOT
filename = fs.save(myfile.name, myfile)
file_url = fs.url(filename)
return render(request, 'upload.html', {
'file_url': file_url
})
else:
return render(request, 'upload.html')

How can I convert a dataframe to csv and save it to return it?

I'm reading a .xlsx file and converting it to .csv but I need to return it as a .csv because I don't have access to the path where it should be stored. I've only been able to return it as a dataframe. Any help will be really appreciated. Thanks.
import pandas as pd
def excel_to_csv(myfile):
print(myfile)
data_xls = pd.read_excel(myfile, index_col=None)
data_xls.to_csv(encoding='utf-8', index=False)
return(data_xls)
myfile = request.FILES['file']
if myfile.name.endswith('.xlsx'):
myfile=excel_to_csv(myfile)
If you're using Django, just save it into /media/ root, then you can access it via url
First you need to know the config of MEDIA_ROOT & MEDIA_URL inside your settings.py.
If it's not exist, then you can create one
[ settings.py ]
MEDIA_ROOT = os.path.join(BASE_DIR, 'myproject/static')
MEDIA_URL = '/media/'
Then, make sure you're already add the media config into your urls.py
from django.conf.urls.static import static
urlpatterns = [
# Project url patterns...
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Since you're mentioned this code myfile = request.FILES['file'], then I assume you're in views.py. Last but not least we need FileSystemStorage API.
There you go
[ views.py ]
from django.core.files.storage import FileSystemStorage
def upload(request):
if request.method == "POST":
csv_file = request.FILE['file']
fs = FileSystemStorage()
name = fs.save(csv_file.name, csv_file)
print(f"file_name = {fs.url(name)}"
return render(request, 'somepage.html')
Access the file via url,
www.yourhost.com/media/file_name
if you just want to read an Excel file and get the same data as csv printed to your screen, the following might be useful.
def excel_to_csv(file):
df = pd.read_excel(file)
csv_data = df.to_csv(encoding='utf-8', index=False)
return csv_data
If you really want to save the file I think I would need more information to the systems your are using and what exactly are you trying to accomplish.

Django/Python: Show pdf in a template

I'm using django 1.8 in python 2.7.
I want to show a pdf in a template.
Up to know, thanks to MKM's answer I render it in a full page.
Do you know how to render it?
Here is my code:
def userManual(request):
with open('C:/Users/admin/Desktop/userManual.pdf', 'rb') as pdf:
response = HttpResponse(pdf.read(), content_type='application/pdf')
response['Content-Disposition'] = 'inline;filename=some_file.pdf'
return response
pdf.closed
The ability to embed a PDF in a page is out of the scope of Django itself, you are already doing all you can do with Django by successfully generating the PDF, so you should look at how to embed PDFs in webpages instead:
Therefore, please check:
Recommended way to embed PDF in HTML?
How can I embed a PDF viewer in a web page?
views.py
from django.shortcuts import render
from django.http import FileResponse, Http404
def pdf(request):
try:
return FileResponse(open('<file name with path>', 'rb'), content_type='application/pdf')
except FileNotFoundError:
raise Http404('not found')
def main(request):
return render(request,'template.html')
url.py
from django.urls import path
from django.conf.urls import url
from . import views
urlpatterns =[path('', views.main, name='main'),url(r'^pdf', views.pdf, name='pdf'),]
template.html
<embed src={% url 'pdf' %}'#toolbar=0&navpanes=0&scrollbar=0'style="width:718px; height:700px;" frameborder="0">

Categories