需要在Django app中编写.wav文件,但不能在Heroku(或S3)

时间:2015-11-10 01:57:22

标签: python django heroku amazon-s3

我有一个Django应用程序,用户上传.wav文件,后端进行一些处理,然后吐出已处理的.wav文件进行下载。部署到Heroku后,我发现我无法将写入wav文件写入Heroku的“临时文件系统”(本地,我正在将.wav文件写入myapp / media)。

SO的共识是你应该使用亚马逊的S3来存储静态文件。我很好。问题是,我正在使用的python函数(以及我所看到的所有其他函数)需要一个文件路径来写入文件。我编写.wav文件的代码:

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)

我研究了boto,django-storages和Heroku的Direct to S3 File Uploads in Python。但是,这些解决方案似乎假设您已经有一个指向的文件(正是我没有可以写入的路径而无法创建的文件)。

Cedar堆栈提供的tmp文件夹可以用于我的目的(虽然由于其不稳定性而不是理想的解决方案),但我甚至无法在Google上找到如何在python / Django应用程序中使用它。 ..

Django / Heroku noob在这里绕圈而疯了!非常感谢任何帮助。

3 个答案:

答案 0 :(得分:2)

好的,我能够通过以下方式解决这个问题:

  1. 使用Python< open()函数创建常规Python文件对象。
  2. 使用wav()将.wav文件写入所述对象。
  3. 使用set_contents_from_file()函数将文件保存到S3。
  4. 我的工作(本地和Heroku)代码:

    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)
    

    注意:

    • 我需要使用' w +'打开文件时的模式。
    • 我需要使用' rewind = True'写信给S3时。
    • 如果output_filename中有路径,则会在我的S3存储桶中重新创建该路径。
    • 输出.wav文件在上传到S3之前写入我的Django应用程序的app根目录。

答案 1 :(得分:2)

您可以使用minio-py库直接使用内存中的内容在S3上创建对象,如下所示:

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>)

答案 2 :(得分:1)

您可以使用boto从s3打开一个对象,然后将其读取到内存中,然后从内存中进行波形操作,就像在这个答案中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)