Reputation: 167
I've got a Django application where users upload a .wav file, the backend does some processing, then spits out a processed .wav file for download. Upon deploying to Heroku, I've discovered that I can't write wav files to Heroku's "ephemeral file system" (locally, am writing .wav files to myapp/media).
The SO consensus is that you should use Amazon's S3 to store static files. I'm fine with that. The problem is, the python function I'm using (and all the other ones I've looked at), need a file path to write the file to. My code that writes the .wav files:
output_path = "..../some_folder"
output_wav = wave.open (output_path, "w")
output_wav.setparams((nchannels, sampwidth, framerate, nframes, comptype, compname))
output_wav.writeframes(scaled_e)
I've researched boto, django-storages, and Heroku's Direct to S3 File Uploads in Python. However, these solutions appear to assume you already have a file to point to (exactly what I can't create without a path I can write to).
The tmp folder the Cedar stack makes available could work for my purposes (though it's not an ideal solution due to its instability), but I can't even find on Google how one would use that in a python/Django app...
Django/Heroku noob here going in circles and going crazy! Any help greatly appreciated.
Upvotes: 4
Views: 596
Reputation: 1700
You can directly create objects on S3 with contents from memory using minio-py library like this:
import os
from minio import Minio
# find out your s3 end point here:
# http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region
client = Minio('https://<your-s3-endpoint>',
access_key='YOUR-ACCESSKEYID',
secret_key='YOUR-SECRETACCESSKEY')
client.put_object('my-bucket', 'my_file_name', <sizeofdata>, <data>)
Upvotes: 2
Reputation: 167
OK, I was able to get this working by:
My working (locally and on Heroku) code:
output_filename = "my_file_name"
output_file = open(output_filename, "w+")
k = Key(bucket)
k.key = output_filename
k.set_contents_from_file(output_file, rewind=True)
Notes:
Upvotes: 2
Reputation: 690
You may be able to open an object from s3 with boto and read it to memory and then make the wave operation from memory like in this answer, How to play WAV data right from memory?:
import wave, StringIO
file_via_s3 = Key(objectkey).get_contents_as_string() #via boto
output_path = StringIO(file_via_s3)
output_wav = wave.open(output_path, "w")
output_wav.setparams((nchannels, sampwidth, framerate, nframes, comptype, compname))
output_wav.writeframes(scaled_e)
...
#save it back to s3
Key(objectkey).set_contents_from_string(output_wav)
Upvotes: 1