The django view function downloads the files:
def download(request):
with open('path','rb') as fh:
response = HttpResponse(fh.read())
response['Content-Disposition'] = 'inline; filename='+base_name_edi
return response
This function downloads the files. But I want to download the files from S3. How to find the path of the S3 File so that this function works?
Related
Currently I have the process of uploading files to s3 broken down to two parts:
download the file locally :
#downloads file from a url to local
def download_url(url, save_path):
r = requests.get(url, stream=True)
with open(save_path, 'wb') as fd:
for chunk in r.iter_content(chunk_size=1024 * 1024):
fd.write(chunk)
upload to s3 :
def create_aws_resource(aws_access_key_id, aws_secret_access_key, aws_default_region):
s3 = boto3.client('s3', aws_access_key_id=aws_access_key_id,aws_secret_access_key=aws_secret_access_key)
return s3
def save_to_s3(bucket,path,save_path,link_save_path, aws_access_key_id, aws_secret_access_key, aws_default_region):
s3 = create_aws_resource(aws_access_key_id, aws_secret_access_key, aws_default_region)
os.chdir(save_path)
filename = link_save_path.split('/')[-1]
s3_path = path+'/'+filename
s3.upload_file(link_save_path, bucket, s3_path)
This process needs to be run on a server and hence I want to eliminate the first step of downloading locally.
Is there a way to directly store files (any files - .xlsx, .pdf, .ods, .xls, .html) to s3?
example : want to upload the file on http://seriestoriche.istat.it/fileadmin/documenti/Tavola_17.1.xls to s3 directly.
Any help would be highly appreciated !!
This worked like a charm for me !
def create_aws_resource(aws_access_key_id,aws_secret_access_key):
s3 = boto3.client('s3', aws_access_key_id=aws_access_key_id,aws_secret_access_key=aws_secret_access_key)
return s3
def save_to_s3(doc_url, doc_name,bucket,s3_path,aws_access_key_id,aws_secret_access_key):
s3 = create_aws_resource(aws_access_key_id,aws_secret_access_key)
try:
# Gets the file as an object
response = requests.get(doc_url)
except:
print('File not downloaded from {doc_url}')
next
try:
# uploads the file to s3
s3.upload_fileobj(io.BytesIO(response.content), bucket, f'{s3_path}/{doc_name}')
print(f'File downloaded from {doc_url} and uploaded to {s3_path}/{doc_name}')
except:
print(f'File not uploaded to {s3_path}')
doc_url - is the document url;
doc_name - is the name you want the file to save as on s3;
s3_path - where you want to save the file
kind of looked at all possible options.
I am using boto3 and python3.6 to upload file to s3 bucket, Funny thing is while json and even .py file is getting uploaded, it is throwing Error 500 while uploading CSV. On successful uplaod i am returning an json to check all the values.
import boto3
from botocore.client import Config
#app.route("/upload",methods = ['POST','GET'])
def upload():
if request.method == 'POST':
file = request.files['file']
filename = secure_filename(file.filename)
s3 = boto3.resource('s3', aws_access_key_id= os.environ.get('AWS_ACCESS_KEY_ID'), aws_secret_access_key=os.environ.get('AWS_SECRET_ACCESS_KEY'),config=Config(signature_version='s3v4'))
s3.Bucket(os.environ.get('S3_BUCKET')).put_object(Key=filename, Body=open(filename, 'rb'), ContentEncoding='text/csv')
return jsonify({'successful upload':filename, 'S3_BUCKET':os.environ.get('S3_BUCKET'), 'ke':os.environ.get('AWS_ACCESS_KEY_ID'), 'sec':os.environ.get('AWS_SECRET_ACCESS_KEY'),'filepath': "https://s3.us-east-2.amazonaws.com/"+os.environ.get('S3_BUCKET')+"/" +filename})
Please help!!
You are getting a FileNotFoundError for file xyz.csv because the file does not exist.
This could be because the code in upload() does not actually save the uploaded file, it merely obtains a safe name for it and immediately tries to open it - which fails.
That it works for other files is probably due to the fact that those files already exist, perhaps left over from testing, so there is no problem.
Try saving the file to the file system using save() after obtaining the safe filename:
upload_file = request.files['file']
filename = secure_filename(upload_file.filename)
upload_file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
and then uploading it (assuming that you've configured an UPLOAD_FOLDER):
with open(os.path.join(app.config['UPLOAD_FOLDER'], filename), 'rb') as f:
s3.Bucket(os.environ.get('S3_BUCKET')).put_object(Key=filename, Body=f, ContentEncoding='text/csv')
return jsonify({...})
There is no need to actually save the file to the file system; it can be streamed directly to your S3 bucket using the stream attribute of the upload_file object:
upload_file = request.files['file']
filename = secure_filename(upload_file.filename)
s3 = boto3.resource('s3', aws_access_key_id='key', aws_secret_access_key='secret')
s3.Bucket('bucket').put_object(Key=filename, Body=upload_file.stream, ContentType=upload_file.content_type)
To make this more generic you should use the content_type attribute of the uploaded file as shown above.
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
I want to upload to Imgur an image that was uploaded to my Flask app. Currently, I save the uploaded file to a temporary file then pass the filename to upload_image. Is there a simpler way that avoids the temporary file?
def upload_image():
file = request.files['file']
filename = secure_filename(file.filename)
target_path = os.path.join(UPLOAD_FOLDER, filename)
file.save(target_path)
im = pyimgur.Imgur(IMGUR_CLIENT_ID)
uploaded_image = im.upload_image(target_path, title=filename)
os.remove(target_path)
return uploaded_image.link
PyImgur only supports passing a filename to upload_image. If it supported passing a file object, you could pass the uploaded file directly to it.
You can use the PyImgur client but build the request yourself. Just do what upload_image does internally except use the uploaded file directly.
from base64 import b64encode
data = b64encode(request.files['file'].read())
client = pyimgur.Imgur(IMGUR_CLIENT_ID)
r = client._send_request('https://api.imgur.com/3/image', method='POST', params={'image': data})
return r['link']
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'