【问题标题】:Need to write .wav files in Django app, but can't on Heroku (or S3)需要在 Django 应用程序中编写 .wav 文件,但不能在 Heroku(或 S3)上
【发布时间】:2016-02-10 20:02:02
【问题描述】:

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

SO 的共识是您应该使用 Amazon 的 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 在这里转圈,发疯!非常感谢任何帮助。

【问题讨论】:

    标签: python django heroku amazon-s3


    【解决方案1】:

    好的,我能够通过以下方式完成此工作:

    1. 使用 Python 的 open() 函数创建常规 Python 文件对象。
    2. 使用 wav() 将 .wav 文件写入所述对象。
    3. 使用 set_contents_from_file() 函数将文件保存到 S3。

    我的工作(本地和 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+”模式。
    • 我需要在写入 S3 时使用“rewind=True”。
    • 如果 output_filename 中有路径,则会在我的 S3 存储桶中重新创建该路径。
    • 输出的 .wav 文件在上传到 S3 之前写入我的 Django 应用的应用根目录。

    【讨论】:

    • w+ 听起来是个不错的用例。来自文档:“w+” - 打开一个文件进行写入和读取。如果文件存在,则覆盖现有文件。如果文件不存在,则新建一个文件进行读写。
    【解决方案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>)
    

    【讨论】:

      【解决方案3】:

      您可以使用 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)
      

      【讨论】:

      • 我可以使用 Python 的 'urllib2.urlopen()' 方法从 S3 中很好地读取对象,该方法创建了一个 wav 模块可以读取的文件对象。这是我坚持的写作对象。能够通过直接写入文件对象并使用“set_contents_from_file”方法来使其工作,如下面的回答中所述。谢谢你的领导!为我指明了正确的方向。
      猜你喜欢
      • 1970-01-01
      • 2012-09-30
      • 1970-01-01
      • 1970-01-01
      • 2017-05-28
      • 1970-01-01
      • 2013-10-31
      • 2018-10-20
      • 1970-01-01
      相关资源
      最近更新 更多