视图使用Heroku和S3处理图像花费太多时间

2024-04-25 12:04:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在Heroku中运行一个Django应用程序,它处理来自用户的多个图像上传并存储到amazons3。问题是这个过程的执行通常需要超过30秒(Heroku的时间执行限制)。在

我对它进行了测试,其中需要较长时间的一行是将图像文件保存在ImageField中的那一行。这样做是因为图像必须由ProcessImageFile()裁剪和处理。但是这个函数花费的时间并不长,而是save方法本身,这可能是因为它在保存文件时将文件逐个存储在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秒上传5张图片在S3中并给出响应。也许解决方案是将所有的图像批量发送到S3,或者以其他方式保存它们,我不知道。在


Tags: theincropformimgnewreturnobjects
1条回答
网友
1楼 · 发布于 2024-04-25 12:04:54

我认为你必须这样向前走:

  • 首先将案例中的images等任何类型的文件保存到本地目录中。

  • 之后,您可以使用Celery将该文件上载或传输到其他地方,该位置可以是像S3这样的远程存储位置。

这是一个开源应用程序,它正在执行你真正想要的任务

Visit Reference: django-queued-storage

安装和使用也非常简单明了:

pip install django-queued-storage

相关问题 更多 >