这个场景下,在用户下载完转换好的文件再删除临时文件的最佳实际是什么?

52 天前
 drymonfidelia
from flask import Flask, request, send_file, abort
import ffmpeg
import os
import tempfile
import time

app = Flask(__name__)

@app.route('/audio_appledevices/<name>.m4a', methods=['GET'])
def convert_audio(name):
    ogg_path = f'./audio/{name}.ogg'
    if not os.path.exists(ogg_path):
        abort(404)
    with tempfile.NamedTemporaryFile(delete=False, suffix='.m4a') as temp_file:
        m4a_path = temp_file.name
    try:
        ffmpeg.input(ogg_path).output(m4a_path, codec='alac').run(overwrite_output=True)
        response = send_file(m4a_path, as_attachment=True, download_name=f'{name}.m4a', mimetype='audio/mp4')
        @response.call_on_close
        def cleanup():
            time.sleep(1)
            if os.path.exists(m4a_path):
                os.remove(m4a_path)
        return response
    except ffmpeg.Error as e:
        abort(500)


if __name__ == '__main__':
    app.run(host='127.0.0.1', port=3389)

除非另开一个线程,不管怎么写临时文件都不能被自动删掉,要不就是 ffmpeg 写不进文件,因为临时文件被占用。 因为 ffmpeg 需要 seekable 的流,所以输出到 IO 流不可行。

请先测试再回复!我让 GPT-4 写了几十个版本,没有一个能用。

请先测试再回复!我让 GPT-4 写了几十个版本,没有一个能用。

请先测试再回复!我让 GPT-4 写了几十个版本,没有一个能用。

请先测试再回复!我让 GPT-4 写了几十个版本,没有一个能用。

2528 次点击
所在节点    Python
27 条回复
esile
52 天前
当然异步队列处理+定时删除
expy
52 天前
try except 一般在 finally 里清理吧。

偏题一下,你这 ogg 转 alac ,ogg 是无损吗?
ho121
52 天前
用临时目录 tempfile.TemporaryDirectory ,所有临时文件写到这个目录里,任务结束后删掉整个目录
sunnysab
52 天前
猜想:tempfile 是基于操作系统临时文件功能实现的(原理是,Windows 下 CreateFile 有个参数指示,Linux 下有 open )。尝试把 delete 参数置为 True (默认值)。
另外,有没有可能是共享写的问题,把打开方式设为 'r+b'。ffmpeg 需要处于同一用户中,这点是应该满足的,实在不行 strace 一下看看是哪一步无权限。

捉个虫,标题中应该是“最佳实践”,而不是“最佳实际”。
sazima
52 天前
bytesio:

```python
process = (
ffmpeg
.input(ogg_path)
.output('pipe:', format='wav')
.run_async(pipe_stdout=True, pipe_stderr=True)
)
out, err = process.communicate()
io = BytesIO(out)

# 创建响应并设置合适的头信息
response = make_response(send_file(io, mimetype='application/octet-stream', as_attachment=True, download_name='example.mp3'))
response.headers['Content-Disposition'] = 'attachment; filename=example.bin'
return response
```
sazima
52 天前
更正:
response.headers['Content-Disposition'] = 'attachment; filename=example.mp3'
Haku
52 天前
定时任务删除转换完后超过 x 天的文件。
rsyjjsn
52 天前
网友只是提供一个解决问题的思路给你,你咋老想着网友写好代码,测试通过,原封不动的回复给你呢?
justNoBody
52 天前
> 请先测试再回复!我让 GPT-4 写了几十个版本,没有一个能用。

???测试再回复???你给我 3000 美金我考虑一下
0o0O0o0O0o
52 天前
你这天天提上班遇到的问题面向 V2EX 上班已经不满足了,还要回答的人自行测试。。。工资给大伙分一下吧
lsk569937453
52 天前
笑死。。。。这是面向 V2EX 编程的社会实践吗?
Hopetree
52 天前
既然是临时文件,当然是规定好清理规则,定时任务定时清理 N 天前生成的文件啊,又简单又快速
djasdjds
52 天前
😅很难想象这是求问的态度
Wh1t3zZ
52 天前
伸手党还这么理直气壮?
gwy15
52 天前
我欠你的
deplives
52 天前
原来 op 就是那个 CORS 和 CSRF 都分不清的人 https://v2ex.com/t/1057881
deplives
52 天前

原来是站长亲戚,怪不得这么理直气壮的伸手
drymonfidelia
52 天前
@expy 不是,所以要定时删除,ogg 源文件有几 TB
@ho121 @sunnysab 这两种方案我都尝试了,执行到 return 那边就会因为文件被 flask 占用无法删除报 500 错误
@sazima 需要 alac 的输出,alac 需要 seekable 的流
@rsyjjsn
@justNoBody
@0o0O0o0O0o
@lsk569937453
@djasdjds
@gwy15 这个问题远没有那么容易解决,我已经想到会有大量无效答案了,写一下试试能不能减少一些
vituralfuture
52 天前
没能把答案喂给你真是抱歉
drymonfidelia
52 天前
@rsyjjsn
@justNoBody
@0o0O0o0O0o
@lsk569937453
@djasdjds
@gwy15 只是讨论最佳实践,我已经用脏实现写了个 cron 定时 rm * 来交差了,知道最佳实践也不会比别人得到更多好处
不会可以不回答,没必要只会阴阳怪气

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1060741

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX