From c7859b0d9b61096df73d150aeae5071a73429055 Mon Sep 17 00:00:00 2001 From: Harmon Date: Wed, 13 Jan 2021 11:36:11 -0600 Subject: [PATCH] Replace file size check in API.media_upload with chunked parameter The simple upload endpoint seems to accept media file sizes much larger than documented, as long as the size after Twitter's API processes the media is below 5 MiB (e.g. through compression, stripping whitespace, etc.). This makes any file size checks prior to uploading to the API potentially overly restrictive. Regardless of this, MAX_UPLOAD_SIZE_STANDARD was already lower than necessary anyway, as the limit appears to be 5 MiB rather than 5 MB, as the error message when using chunked upload for a file larger than 5 MiB, "File size exceeds 5242880 bytes.", indicates. The simple upload endpoint seems to consistently respond with a 413 Payload Too Large HTTP response status code when the uploaded file is too large, even after being processed, which should make it fairly apparent that the file is too large. Most GIFs should be under 5 MiB, but for larger GIFs that the simple upload endpoint will error for, using the chunked parameter will be necessary. Adding this parameter also allows chunked upload of images less than 5 MiB as desired. --- tweepy/api.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/tweepy/api.py b/tweepy/api.py index 6cf3c03..69b8bde 100644 --- a/tweepy/api.py +++ b/tweepy/api.py @@ -13,8 +13,6 @@ from tweepy.utils import list_to_csv IMAGE_TYPES = ['gif', 'jpeg', 'png', 'webp'] -MAX_UPLOAD_SIZE_STANDARD = 4883 # standard uploads must be less than 5 MB - class API: """Twitter API""" @@ -216,7 +214,8 @@ class API: require_auth=True )(*args, **kwargs) - def media_upload(self, filename, file=None, *args, **kwargs): + def media_upload(self, filename, file=None, chunked=False, + *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/media/upload-media/api-reference/post-media-upload :allowed_param: """ @@ -225,15 +224,12 @@ class API: location = file.tell() h = file.read(32) file.seek(location) - size_bytes = os.stat(file.fileno()).st_size - else: - size_bytes = os.path.getsize(filename) file_type = imghdr.what(filename, h=h) or mimetypes.guess_type(filename)[0] - if file_type in IMAGE_TYPES and size_bytes < MAX_UPLOAD_SIZE_STANDARD * 1024: - return self.simple_upload(filename, file=file, *args, **kwargs) - else: + if chunked or file_type == 'video/mp4': return self.chunked_upload(filename, file=file, file_type=file_type, *args, **kwargs) + else: + return self.simple_upload(filename, file=file, *args, **kwargs) def simple_upload(self, filename, file=None, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/media/upload-media/api-reference/post-media-upload -- 2.25.1