Python: Getting local file path from request.files - python

I need help uploading a file directly from an HTML form to an API. I've seen this being done for remote URLs, but I don't know how to do this for local files? I tried writing this, but its not working:
uploadmedia = request.files['fileupload']
client = Client('thisismykey')
with open(uploadmedia, 'rb') as file:
new_upload = client.uploads('<space-id>').create(file)
The line client.uploads is what is specified in the API docs here. I just need to be able to get the file path.
The comments suggest the following:
# you can use either a file-like object or a path.
# If you use a path, the SDK will open it, create the upload and
# close the file afterwards.
I am assuming that request.files['fileupload'] is a file like object, so I just passed that along.
The above code gives me the following error:
File "D:\Gatsby\submission\flask-tailwindcss-starter\app\__init__.py", line 28, in index
with open(uploadmedia, 'rb') as file:
TypeError: expected str, bytes or os.PathLike object, not FileStorage
I know that in this example, uploadmedia.filename would get me the file's name, but what is the attribute for the path? How do I do that?

The request.files['file'] is an instance of a FileStorage class. refer to api, you cannot use with open(uploadmedia, 'rb') as file: .
try using stream attribute :
uploadmedia = request.files['fileupload']
client = Client('thisismykey')
new_upload = client.uploads('<space-id>').create(uploadmedia.stream)

Related

Open an image in python and upload it to S3

I was trying to open a file/image in python/django and upload it to s3 but I get different errors depending on what I try. I can get it to work when I send the image using the front end html form but not when opening the file on the back end. I get errors such as "'bytes' object has no attribute 'file'" Any ideas how to open an image and upload it to s3? I wasn't sure if I was using the correct upload function, but it worked when I received the file from an html form instead of opening it directly.
image = open(fileURL, encoding="utf-8")
S3_BUCKET = settings.AWS_BUCKET
session = boto3.Session(
aws_access_key_id=settings.AWS_ACCESS_KEY_ID,
aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY,
)
s3 = session.resource('s3')
s3.Bucket(S3_BUCKET).put_object(Key='folder/%s' % fileName, Body=image)
Thanks.
The open command return a file object. Therefore Body=image does not contain the actual contents of the object.
Since you want to upload an existing object, you could use:
Key = 'folder/' + fileName
s3.Object(S3_BUCKET, Key).upload_file(fileURL)

File upload at web2py

I am using the web2py framework.
I have uploaded txt a file via SQLFORM and the file is stored in the "upload folder", now I need to read this txt file from the controller, what is the file path I should use in the function defined in the default.py ?
def readthefile(uploaded_file):
file = open(uploaded_file, "rb")
file.read()
....
You can do join of application directory and upload folder to build path to file.
Do something like this:
import os
filepath = os.path.join(request.folder, 'uploads', uploaded_file_name)
file = open(filepath, "rb")
request.folder: the application directory. For example if the
application is "welcome", request.folder is set to the absolute path
"/path/to/welcome". In your programs, you should always use this
variable and the os.path.join function to build paths to the files you
need to access.
Read request.folder
The transformed name of the uploaded file is stored in the upload field of your database table, so you need a way to query the specific record that was inserted via the SQLFORM submission in order to get the name of the stored file. Here is how it would look assuming you know the record ID:
stored_filename = db.mytable(record_id).my_upload_field
original_filename, stream = db.mytable.my_upload_field.retrieve(stored_filename)
stream.read()
When you pass a filename to the .retrieve method of an upload field, it will return a tuple containing the original filename as well as the open file object (called stream in the code above).

mutagen read TemporaryUploadedFile in django

I want to validate my mp3s before saving them to disk, using Mutagen. However with mutagen I can only open a file if it's on disk. Is there a way around this? I would like to be able to do this:
files = request.FILES
mp3 = files.get('mp3')
mp3_audio = MP3(mp3)
Gives me the error:
TypeError: invalid file: <TemporaryUploadedFile: test.mp3 (audio/mpeg)>
A TemporaryUploadedFile file object is already on disk, in a directory reserved for temp files. To analyze it for validity, call a method to get the full path:
files = request.FILES
mp3_temp = files.get('mp3')
mp3_audio = MP3(mp3_temp.temporary_file_path())
see docs at TemporaryUploadedFile.temporary_file_path()

How do I open a FITS file from a URL in astropy?

I have a .fits file at a URL that I would like to read into Python as if was just on my machine. What I've tried is:
import urllib2 as url, astropy.io.fits as fits
target_url = 'https://s3.amazonaws.com/bdnyc/spex_prism_U50171_0835%2B19_chiu06.fits'
obj = url.urlopen(target_url)
dat = fits.open(obj)
But I just get IOError: File-like object does not have a 'write' method, required for mode 'ostream'.
Even if I set mode='readonly' in fits.open() it says it can't write to the file-like object.
Is there a way to open .fits files from a URL? Or to convert the .fits file bytes returned by urlopen() back into an HDUList?
Based on the documentation of astropy.io.fits.open, it has an option to read the contents of a .fits file from a URL:
cache : bool, optional
If the file name is a URL, download_file is
used to open the file. This specifies whether or not to save the file
locally in Astropy’s download cache (default: True).
Which means you didn't have to use urllib2. You can just feed target_url to fits.open right away, as it calls astropy.utils.data.download_file on the URL before opening it. See my code below.
In [1]: import astropy.io.fits as fits
In [2]: target_url = 'https://s3.amazonaws.com/bdnyc/spex_prism_U50171_0835%2B19_chiu06.fits'
In [3]: dat = fits.open(target_url)
In [4]: dat
Out[4]: [<astropy.io.fits.hdu.image.PrimaryHDU at 0x219a9e8>]

How do I allow users to download a MIDI file with Flask without getting a 0 byte download?

I am writing an application that creates a midi file using the MIDIUtil library. When the user submits an HTML form, a midi file object is created with MIDIUtil. How do I allow the user to download this as a .mid file? I have tried the following code, but I end up downloading a file of 0 bytes.
return Response(myMIDIFile, mimetype='audio/midi')
I use a variant of the following code to allow my users to download images they generate. The below code should work for you. Please note that you will most likely need to specify the full server path to the file being downloaded.
from flask import send_file
download_filename = FULL_PATH_TO_YOUR_MIDI_FILE
return(send_file(filename_or_fp = download_filename,mimetype="audio/midi",as_attachment=True))
I ended up using this, and it worked.
new_file = open('test.mid', 'wb')
myMIDI.writeFile(new_file)
new_file.close()
new_file = open('test.mid', 'rb')
return send_file(new_file, mimetype='audio/midi')
Might want to just try using send_file
from flask import send_file
return send_file("yourmidifile.mid", as_attachement=True, mimetype="audio\midi")

Categories

Resources