/upload_to_vimeo/ 'TypeError' 处的 AttributeError 对象没有属性 'message'

AttributeError at /upload_to_vimeo/ 'TypeError' object has no attribute 'message'

将视频上传到 vimeo 时抛出此错误 以下是代码 观看次数

def upload_to_vimeo(request):
    token = 'xxxxx'
    if request.method == 'POST':
        form = VideoUploadForm(request.POST, request.FILES)
        if form.is_valid():
            v = vimeo.VimeoClient(
                token=token,
            )
            v.upload(request.FILES['video_file'])
            return HttpResponseRedirect(request.META.get("HTTP_REFERER"))
    else:
        form = VideoUploadForm()
    return render(request, 'forms/video_upload_form.html', {'form': form})

模板

 <form action="" method="POST" enctype="multipart/form-data">
                    {% csrf_token %}
                    <input type="file" name="video_file">
                    <input type="submit" class="button inline-block bg-theme-1 text-white mt-5" value="Upload">
                </form>

回溯:

File "/home/biju/Desktop/Dev/multitenant/lib/python3.8/site-packages/vimeo/upload.py" in __perform_tus_upload
  143.             with io.open(filename, 'rb') as fs:

During handling of the above exception (expected str, bytes or os.PathLike object, not TemporaryUploadedFile), another exception occurred:

File "/home/biju/Desktop/Dev/multitenant/lib/python3.8/site-packages/django/core/handlers/exception.py" in inner
  34.             response = get_response(request)

File "/home/biju/Desktop/Dev/multitenant/lib/python3.8/site-packages/django/core/handlers/base.py" in _get_response
  115.                 response = self.process_exception_by_middleware(e, request)

File "/home/biju/Desktop/Dev/multitenant/lib/python3.8/site-packages/django/core/handlers/base.py" in _get_response
  113.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/home/biju/Documents/mtenant/client_admin/views.py" in upload_to_vimeo
  787.             v.upload(request.FILES['video_file'])

File "/home/biju/Desktop/Dev/multitenant/lib/python3.8/site-packages/vimeo/upload.py" in upload
  71.         return self.__perform_tus_upload(filename, attempt, chunk_size=chunk_size)

File "/home/biju/Desktop/Dev/multitenant/lib/python3.8/site-packages/vimeo/upload.py" in __perform_tus_upload
  152.             raise exceptions.VideoUploadFailure(

File "/home/biju/Desktop/Dev/multitenant/lib/python3.8/site-packages/vimeo/exceptions.py" in __init__
  93.         super().__init__(response, message)

File "/home/biju/Desktop/Dev/multitenant/lib/python3.8/site-packages/vimeo/exceptions.py" in __init__
  30.         self.message = self.__get_message(response)

File "/home/biju/Desktop/Dev/multitenant/lib/python3.8/site-packages/vimeo/exceptions.py" in __get_message
  23.             message = getattr(response, 'message')

Exception Type: AttributeError at /upload_to_vimeo/
Exception Value: 'TypeError' object has no attribute 'message'

Vimeo 端的一些草率编码,此处显示了细微差别:

       try:
  ...:     int("not an int")
  ...: except ValueError as e:
  ...:     print("e is an exception: {} / {}".format(type(e) is Exception, isinstance(e, Exception)))
  ...:     
e is an exception: False / True

所以他们的异常检查对于异常的任何子类都失败了(阅读:总是)。而且由于它们不会抛出带有消息属性的异常,因此您最终会遇到 AttributeError。

但无论如何您不会有太多事情要做,因为如果他们正确编码,他们会告诉您:'Unexpected error when uploading through tus.'。归结为您未能在 3 次重试内从 Tus 获得偏移量(在何处重新开始当前块的上传)。祝狩猎顺利!

处理评论

request.FILES 是文件 objects 的数组。不是文件 名称 的数组。 api 想要文件名,但他们不检查是否获得文件名或是否支持类文件对象。他们也做可怕的事情:

        try:
            return os.path.getsize(filename)
        except TypeError:
            return len(filename.read())

所以理论上它们支持类文件对象,但显然不完整。另外, len(filename.read()) 对你的服务器内存来说是非常危险的,特别是对于并行的视频文件,因为整个文件将被读入内存。我越读这个 API,我就越不想使用它 ;)。

无论如何,您应该在设置中添加以下内容:

FILE_UPLOAD_HANDLERS = [
 'django.core.files.uploadhandler.TemporaryFileUploadHandler'
]  # Removed MemoryFileUploadHandler

如评论所述,这会删除我们可用的 MemoryFileUploadHandler, so we can rely on temporary_file_path。此外,Django 根据文件大小在内存和磁盘存储之间切换(上次我检查大约 3MB 从内存转到磁盘上)。这是 a) 很少使用和 b) API 不能与它们一起使用。

然后将路径传递给 Vimeo:

file_obj = request.FILES['video_file']
path = file_obj.temporary_file_path()  # method not attribute
try:
    v.upload(path)
except VimeoUploadFailure:
    print("Uh oh")
finally:
    file_obj.close()  # Theoretically this should remove the file
    if os.path.exists(path):
        os.unlink(path)  # But this will do it, barring permissions