Quick and dirty way to access files external to Django? - python

I'm working on a demo for a program that creates some files on its own directory. This demo will be shown to someone physically far, via VPN, so I made a simple django project just to receive an input, call some scripts and display the output - the generated file. However, I don't have permission to open the file to display it since it's on a directory outside of the django project (the result is a permission denied error).
I'm aware it's not good practice or even safe for a web server to have access to files outside of its directories, but since this will run in a closed environment for a short amount of time only, is there a workaround?

Think of it this way - If web server can generate the files , it can display them also.
As for your answer - if you know the path of the file, use the python open built in method to open the file and render the result to a template.
data = open('file_path').read().decode('utf-8')
render(request, template, context={data:data})

Related

Change the Directory when Upload a file

I would like to change the default location use by the browser when uploading a file.
I mean I have a website and when the client clic on upload file, I would like to point to a target directory (ie Downloads) instead of Desktop.
How can I do it ?
My website use Flask / Python
That's probably impossible. It's the client who choose's where to save data not the server.
You'll need to know the computer's folders paths. And that's called Hacking wich is illegal.

Is it wrong to use modules like wget to let users download files on django?

I am working on a django application in which users can download their own files. I need to make the files secure and only let them download it.
At first, I was thinking of using something like
{%if files%}
<a href='/media/files/pics/photo.png' download>
Then i realised that anyone can brute force my site and get any files. So I thought of handling the download through views. I am very beginner and don't know how to make my own download view. So I used something like:
at views.py
def download(id):
file = data.objects.get(pk=id)
url = file.fileurl
filename = wget.download(url)
and call the function when the user want to download the file. I am using wget module. I think I am doing wrong, So I decided to ask for some suggestions.
At last my question is :
Is it wrong to use other modules to download files? Or how to write a download view on Django?
Thank you!!
How to download a file in Django depends on your needs. any library that can download and store the file somewhere should be fine. How to serve them to other users on the other hand is a different story.
As you mentioned, you need URLs to be private so only the authorized user can download the file. In this case, You can set up a view and authorize the user and then let your webserver know that it should serve a specific file to this user.
You can use X-Accel-Redirect if you're using Nginx. Other web servers such as Apache have a similar option named X-Sendfile.
Take a look here for nginx example: Django and Nginx X-accel-redirect
As for saving files, you should save the files somewhere and store the path to that file in the database and link it to a user (with a foreignkey for example) and let only the owner of the file download the file. It is also worth mentioning that downloading files might take a long time so it's a good idea to lunch a background task for downloading the files and allow users to start the download when it's finished. You can take a look at Celery for background tasks.

Building a web application that can work with local files

I'd like to build an application (local, not online) by using front-end web technology for the UI, the application simply displays PDFs and has a few text fields for the user to fill in with regards to the current PDF they're viewing, the user can then export their notes and a file path to the document in CSV file format.
comment about file, some more notes, C:\somefolder\doc1.pdf
comment about file, some more notes, C:\somefolder\doc2.pdf
My first issue, JavaScript can't access the local file system, so I used a file upload form which worked except the filepaths were shown as blob filepaths and not the actual system file path. Other than that my "application" worked as intended.
I went and learned Flask in hopes of using python for the back end, which works great except when I pass in the file path to the pdf C:\SomeFolder\doc1.pdf inside the 'src' attribute for an Chrome says it can't access local files. SO I'm back to sqaure one!
How can I go about building this application with local file access?
If you need to access the local files, you can create an endpoint in flask that launches a file dialog GUI. This only works because you application is hosted locally. You can use either tkinter or the native windows API using win32ui.
Assuming you are using the standard Flask format:
from app import app
#app.route('/file_select', methods=['GET', 'POST'])
def file_select():
from tkinter import Tk
from tkinter.filedialog import askopenfilename
root = Tk()
root.withdraw()
# ensure the file dialog pops to the top window
root.wm_attributes('-topmost', 1)
fname = askopenfilename(parent=root)
return jsonify({'filepath': fname})
or using the win32ui API
#app.route('/file_select', methods=['GET', 'POST'])
def file_select():
import win32ui
winobj = win32ui.CreateFileDialog(1, ".pdf", "", 0,
"PDF Files (*.pdf)|*.pdf|All Files (*.*)|*.*|")
winobj.DoModal()
return jsonify({'filepath': winobj.GetPathName()})
Now just add a button that points to the /file_select route and you will open a file dialog via the python local server and return the selected file.
Assuming you are accessing the page via http://localhost:8080/page or something like that, you should serve your content via that approach. Effectively, rather than serving the files as paths on the local file system, you would create an application route and associate it with a handler than retrieves the appropriate PDF from the local filesystem, and then sends back a response containing Content-Type: application/pdf in the HTTP response headers and the bytes of the PDF file in the response body.
To avoid duplicating someone else's solution for the approach described about, I would recommend taking a look at this answer for "Flask handling a PDF as its own page".
Because you are technically sending the response back from localhost -- or whatever name you are serving it with -- rather than trying to load a local file directly from the client's web-page, Chrome shouldn't throw any complaints.
Of course, it's worth noting that best practices should be taken when determining the file to load, if this were going to be anything more than a learning project. In any legitimate system that did this kind of thing, it would be necessary to perform checks on the requested files to ensure a malicious user does not abuse the application to leak files from the local filesystem, beyond those files which are intended to be served. (To that end, you typically might have the src element contain a parameter that is set to the hash/unique ID for the file which is then mapped via some database to the correct path of the file. Alternatively, you might use a param in the src that contains the name of the file without the full path, and then check that the user-provided value for that parameter in the request does not contain any characters outside of a charset like [a-zA-Z0-9_-].) Ultimately, it sounds like this particular warning doesn't apply to your case, but still providing it in case anyone else reads this in the future.
I think mht is exactly what you want. mht is a file extension recongnized by IE. Internally it is an HTML file. IE (only) treats a mht file with the same security restrictions that a exe might have. You could access the file system, delete a file, display a file etc.. It is everything that html/javascript security was trying to prevent. Now that IE has changed significantly I don't know what the support for this is nowadays. I couldn't find a reference page to give you a link, but it is simple enough - just save a html file with an mht extension

How to serve non-local images from localhost

I'm writing a Python script that works with images on the user's computer, my plan is to display these images on a webpage via bottle.py (which can change if need be) on localhost. The images and the script could be located anywhere, however serving from localhost doesn't allow me to display images with a file:/// path for security reasons, so I'm stuck as to how I can achieve this. I basically want bottle's static_file function but with multiple files and within a HTML template. Is this at all possible without moving the images?
No, the browser sandbox won't and shouldn't allow this. Think about it this way: if you were able to display images from the user's computer without his explicit approval, they would be part of the DOM and what would stop a script from manipulating them or sending to a server without the user's knowledge?

download file link produces 404 page

I am trying to create a link that allows a user to download a zip file that's been generated earlier in the python script. The script then writes an HTML link to a web page. The user should be able to click the link and download their zip file.
import os,sys
downloadZip = ("http://<server>/folder/structure/here/" + zipFileName + ".zip")
print """<h3><a href="{}" download>Download zip file</a></h3>""".format(downloadZip)
The result is a link that when clicked opens a 404 page. I've noticed that on that page, it displays
Physical Path C:\inetpub\wwwroot\inputted\path\here\file.zip
I am testing this on the same server the processing is occurring on. I wouldn't think that should make a difference, but here I am. The end result should be a zip file downloaded to the user's pc.
Not sure if this would be helpful or not but I have noticed that some 'server package apps' disallow the execution/download of certain filetypes. I had a similar thing happen years ago.
To test if this is the case, create a new folder in your web directory and add an index.html page with some random writing (to identify that you have the correct page). Quickly try to access this page.
Next create a .zip file, put it in the same folder as the index.html file you just created, and add a Download link on the index.html page.
Now revisit the page, and try to download the file you created. If it works then there is a problem elsewhere, if it doesn't then whatever server package application you are using probably set Apache to block .zip files by default. Hope this helps buddy :)

Categories