Django HttpResponse - open file object in default editor - django

Take the following code snippet of a Django view
def serve_file(request)
path = 'C:/path_to_file/test.html'
file_name = os.path.basename(path)
response = HttpResponse(path)
response['Content-Disposition'] = 'attachment; filename={0}'.format(file_name)
return response
The file is served in the response and the browser asks do I want to open, but when it opens in the default editor, it opens from 'Temporary INternet Files'. How can I have this open from its original location at 'C:/path_to_file/'?

There's a fundamental disconnect here. When Django serves the file, even if it's on your own computer, the browser has to download it before it can be accessed. So the actual file that would be opened is not at the original C:/... location, but in whatever directory the file was downloaded to.
If you need users of your website to be able to edit files that persist on your server, that will require much more work than this. Downloading a file creates a copy of it on the user's computer.

Related

Files are being downloaded at pythonanywhere server and user laptop/pc too. How to restrict to write at pythonanywhere server

Problem is i have hosted at pythonanywhere using django.Video is downloaded at pythonanywhere server and user/client system too.Thats why i used os. remove(path).After downloading it removes from server.
Is there any ways files donot write on pyhtonanywhere server. so that i donot use os.remove(path).
How to restrict to write at pythonanywhere server. Only to download at user system.
def fb_download(request):
link = request.GET.get('url')
html= requests.get(link)
try:
url= re.search('hd_src:"(.+?)"',html.text)[1]
except:
url= re.search('sd_src:"(.+?)"',html.text)[1]
path=wget.download(url, 'Video.mp4')
response=FileResponse(open(path, 'rb'), as_attachment=True)
os.remove(path)
return response
If I understand correctly, you're trying to get a request from a browser, which contains a URL. You then access the page at that URL and extract a further URL from it, and then you want to present the contents of that second URL -- a video -- to the browser.
The way you are doing that is to download the file to the server, and then to serve that up as a file attachment to the browser.
If you do it that way, then there is no way to avoid writing the file on the server; indeed, the way you are doing it right now might have problems because you are deleting the file before you've returned the response to the browser, so there may (depending on how the file deletion is processed and whether the FileResponse caches the file's contents) be cases where there is no file to send back to the browser.
But an alternative way to do it that might work would be to send a redirect response to the URL -- the one in your variable url -- like this, without downloading it at all:
def fb_download(request):
link = request.GET.get('url')
html= requests.get(link)
try:
url= re.search('hd_src:"(.+?)"',html.text)[1]
except:
url= re.search('sd_src:"(.+?)"',html.text)[1]
return redirect(url)
By doing that, the download happens on the browser instead of on the server.
I don’t understand javascript really good,
But i think if you download the file to the server
And then you can download the file to the use using JS
And i think you can use

Is there any way to bypass the server my Django site is hosted on when uploading files, and just immediately upload to S3 instead?

I am using boto3 to upload massive media files (2GB+) from my Django website to an s3 storage bucket. My issue is that when uploading a file larger than 2.5MB - the connection is immediately timed out and no debug information displays
I assume what is happening is that Django is using the temporary file upload handler, but the temp file handler won't work on the server the Django app is running on (pythonanywhere free tier).
This works flawlessly locally, because it just has to copy to the OS, not the server. I would like to skip the web server so I am not using all the storage/bandwidth
s3.upload_file needs the local path of the file in order to be able to upload it to S3, the only way I could find to do that is grab the temp_path of the file.
# method to chunk the upload process if file is over 2.4MB
def s3_multipart_upload(f, video_id):
# our server path
file_path = "media/"
new_folder = str(video_id)+"/"
file_name = f.name
server_path = file_path + new_folder + file_name
# the file gets copied to ~/tmp/ so grab that path
local_path = f.temporary_file_path()
# create s3 client connection
s3 = boto3.client('s3', settings.AWS_S3_REGION_NAME, **credentials)
config = TransferConfig(
multipart_threshold=1024 * 25,
max_concurrency=10,multipart_chunksize=1024 * 25,
use_threads=True
)
s3.upload_file(
local_path,
settings.AWS_STORAGE_BUCKET_NAME,
server_path,
ExtraArgs={'ACL': 'public-read'},
Config=config,
Callback = ProgressPercentage(local_path)
)
return
I would like to be able to upload directly to S3, straight from my website, without the files going through the server (python anywhere). If there is a cleaner way of doing this, a better server I should use, or if there is a way to upload the file without copying to temp first - I'm all ears.
(I am also new to Python/Django/Servers in general, so any help is appreciated)
I am not sure if you have found the answer but you can upload content directly to s3 using signed url mechanism.
Request Signed URL for s3 from django backend
Use frontend to upload content directory to s3
But I would suggest do this only if you have bigger media files to be uploaded.
I found this as secured approach.
https://www.serverless.com/blog/s3-one-time-signed-url

URL shortening using UUID while serving files nginx django

Using Django2 and nginx, users can upload files (mainly pic,vids) and I want to serve those files by masking the full url path.
This is the example structure I expect to see but I don't want users to know about this structure or even the image filename.
domain.com/media/user/pictures/Y/M/D/image1.jpg
I want the user to see the above image through a url like this and the random UUID number changes for each file and that number can point to any type of file.
domain.com/media/23kj23l9ak3
When the file is uploaded the original name, permissions assigned (public, friends, private), file path and the UUID that is generated stored in the database) but the file is stored on the filesystem or remote location.
I've never got to this point before and I would like to know what the modern way of doing it would be or let me know what technology/features of django/nginx can help me solve it.
I'm not entirely sure why you want to do this, rather than simply using the UUID as the filename of the uploaded file, but you certainly can do it.
One good way would be to route the request via Django, and use the custom X-Accel-Redirect header to tell nginx to respond with a specific file. You would need to store both the UID and the actual path in a Django model. So the nginx config would be something like:
location /protected/ {
internal;
alias /media/user/; # note the trailing slash
}
and the Django view would be:
def user_picture(request, uuid):
image = MyModel.objects.get(uuid=uuid)
response = HttpResponse(status=200)
response['X-Accel-Redirect'] = '/protected/' + image.file.path
return response

Django and/or Apache: serve (static) files with a different name

I store a lot of files, using a hash as file name, but when a user wants to download it, I would like to be able to give the file a new name.
Let's say the user navigates to www.myurl.com/userxy/files/some.pdf. In the Django View for that url, I can now look up the correspondig file, which might be on the server on .../files/46dfa12bbf32d523fbb3642dfee45bb4.
So how can I now get this file to be served as some.pdf to the client? Do I have to copy the file first, and giving it a different name on the disc or can I somehow serve the original file? Is what I'm trying at all good practice?
I also don't know on what level (Apache or Django) this type of operation is best handled. But since I didn't find anything about this for Apache or Django, I would be interested in solutions for either of them.
Quoting django docs Telling the browser to treat the response as a file attachmen, you should inform it in response:
>>> response = HttpResponse(my_data, content_type='application/vnd.ms-excel')
>>> response['Content-Disposition'] = 'attachment; filename="some.pdf"'

redirect and force download

this is my problem: I have some pdf files on a server, my Django web-application
is hosted on another server (not the same of the pdf files).
On my appplication i know the pdf files link on the other server. I want to download that pdf files through my application without read them on web server application.
I try to explane. If i click on download link, my browser shows the pdf into his internal pdf viewer. I don't want this, i want that on click on a button the user will download the file without open it on internal browser.
I looked here: http://docs.djangoproject.com/en/dev/ref/request-response/#telling-the-browser-to-treat-the-response-as-a-file-attachment
but this is not a good way for me, cause it requires that I read the file inside my web-application and after return it to the user.
Is it possible??
Hmm, sounds like the wrong tool for the job. You can't really "redirect" and modify the response header, which means using django just to set the Content-Disposition header would require you to stream the file through django, then have django stream it to the client.
Let a lighter weight web server handle that. If you happen to be using nginx, here's an awesome solution that fits your scenario 99% (the 1% being it's rails setting the header that nginx is waiting for).
If all you want is to set the header and the file doesn't need django processing, it would be even easier to proxy!
If you are not using nginx, I would change the title to a web server specific question about proxying a file & setting headers.
I had a similar problem recently. I have solved it downloading the file to my server and then writing it to the HttpResponse
Here is my code:
import requests
from wsgiref.util import FileWrapper
from django.http import Http404, HttpResponse
def startDownload():
url, filename, ext = someFancyLogic()
request = requests.get(url, stream=True)
# Was the request OK?
if request.status_code != requests.codes.ok:
return HttpResponse(status=400)
wrapper = FileWrapper(request.raw)
content_type = request.headers['content-type']
content_len = request.headers['content-length']
response = HttpResponse(wrapper, content_type=content_type)
response['Content-Length'] = content_len
response['Content-Disposition']
= "attachment; filename={0}.{1}".format(filename, ext)
return response