Просмотр занимает слишком много времени для обработки изображений с Heroku и S3 - PullRequest
2 голосов
/ 17 октября 2019

Я использую приложение Django в Heroku, которое обрабатывает несколько загрузок изображений от пользователя и сохраняет их в Amazon S3. Проблема заключается в том, что для выполнения этого процесса обычно требуется более 30 секунд (ограничение по времени выполнения Heroku).

Я проверил это, и строка, которая занимает больше времени, является той, которая сохраняет файл изображения в ImageField. Это делается так, потому что изображение должно быть обрезано и обработано ProcessImageFile (). Однако эта функция не занимает много времени, но сам метод сохранения, возможно, потому что он сохраняет файлы в S3 один за другим, сохраняя их.

Вот представление (пропущены нерелевантные строки):

    @login_required
    def image_create(request):
        if request.method == 'POST':
            images = request.FILES.getlist("files")
            crop_points = json.loads( request.POST.get('crop_points'))

            #Validation of inputs in the form: images and other fields
            if len(images) < 3 : return JsonResponse({'val_result': 'min_error'})
            if len(images) > 12: return JsonResponse({'val_result': 'max_error'})

            #We Create the gallery, iterate over the images provided by the form, validate, insert custom fields and save them in bulk associating it to the gallery.

            with transaction.atomic():            
                new_items = []    
                gallery = Gallery.objects.create( user=request.user )

                for i, img_file in enumerate(images):
                    new_item = Image()
                    new_item.user = request.user            

                #-----THIS IS THE PART WHICH TAKES MOST OF THE VIEW PROCESSING TIME: IT IS NOT THE ProcessImageFile FUNCTION, BUT THE SAVE METHOD ITSELF
                    new_item.image.save( 'img'+ str(i) + '.jpg', content = ProcessImageFile(img_file, crop_points), save=False   )
                #---------------------------------------------------------------------------------------------------------------------------------------

                new_items.append( new_item )                
                created_objects = Image.objects.bulk_create( new_items )
                Belonging.objects.bulk_create( [ Belonging(gallery=gallery, content_id = item.id) for item in new_items] )
                for img in created_objects:
                    img.create_tags(gallery = gallery) #<-We save the notifications for bulk create

                return JsonResponse({'status': 'ok', 'gallery': gallery.id})

        else:
            form = MultiUploadImageForm()

        return render(
            request,
            'upload/create.html',
            {'form': form}
        )

#I THOUGHT THIS COULD BE THE FUNCTION TAKING TIME BUT IT IS NOT:
def ProcessImageFile(img_file, crop_points):
    img = ImageProcessor.open(img_file)
    cropped_img = img.crop( ( int(crop_points[0]), int(crop_points[1]), int(crop_points[2]), int(crop_points[3])))
    img_io = BytesIO()
    cropped_img.save( img_io, format='JPEG', quality=100)
    return ContentFile( img_io.getvalue())

Я уже пытался использовать Celery для обработки загрузки файла в отдельной задаче, но проблема здесь заключается в передаче запроса илифайлы изображений для задачи, так как они должны быть сериализованы. В любом случае, я полагаю, что здесь есть что-то неэффективное, и что этот простой вид не должен занимать более 30 секунд для загрузки пяти изображений в S3 и возврата ответа. Возможно, решением будет отправить все изображения вместе на S3 или сохранить их другим способом, я не знаю.

1 Ответ

2 голосов
/ 26 октября 2019

Я думаю, что вам нужно двигаться вперед, как это:

  • Сначала сохраните любой тип файла, например images в вашем случае, в локальный каталог.

  • После этого вы можете загрузить или передать этот файл в другое место, которое может быть удаленным хранилищем, например, S3, используя Сельдерей .

Вот Open- исходное приложение, которое выполняет именно ту задачу, которую вы действительно ищете;

Посетите ссылку: django-queued-storage

Установка и использованиетоже очень просто и понятно:

pip install django-queued-storage
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...