S3上传/下载超时问题

时间:2019-06-15 19:11:08

标签: ruby-on-rails amazon-s3 zip aws-sdk-ruby

我正在尝试使用S3文件存储和通过Heroku上的ruby-on-rails应用程序进行sdk访问来创建带有地理标记图像的kmz格式文件。

在加载“项目”视图时,我正在运行文件进程,但是为访问S3和处理文件而编写的实例方法大约需要40秒钟才能完成,从而导致504超时错误。

我已经在研究S3本身的压缩而不需要本地下载,但这似乎不可行。有没有更好的方法来加快下载/上传过程的速度,或者有更好的运行它来避免超时的发生?

项目控制器中的方法:

  # GET /projects/1
  # GET /projects/1.json
  def show
   @pictures = @project.pictures.all
   @project.generate_kml
   @project.download_project
   @project.generate_kmz
  end

详细信息:

def generate_kml
        content = []
        content.push('<?xml version="1.0" encoding="UTF-8"?>')
        content.push('<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">')
        content.push('<Document>')
        content.push("<name>#{self.id}.kmz</name>")
        #cycles through each picture in db for the current project
        self.pictures.each do |pic|
            pic_title = pic.image.to_s.split('/').last
            content.push('<Placemark>')
            content.push("<name>#{pic_title}</name>")
            content.push('<description>')
            content.push('<![CDATA[')
            line = '<img style="max-width:1000px;" src="' + '' + pic_title + '">' 
            content.push(line)
            content.push(']]>')
            content.push('</description>')
            content.push('<Point>')
            content.push("<coordinates>-#{pic.long},#{pic.lat}</coordinates>")
            content.push('</Point>')
            content.push('</Placemark>')
        end
        content.push('</Document>')
        content.push('</kml>')
        #pushes upload to S3 folder
        s3 = Aws::S3::Resource.new
        obj = s3.bucket(ENV['S3_BUCKET']).object("uploads/" + "#{self.id}" + "/doc.kml")
        File.open("kml_temp", "w+") { |f| 
        f.puts(content)
        obj.put(body: f)
        }
    end

    def generate_kmz
        #create
        directory_to_zip = "/tmp/#{self.id}"
        output_file = "/tmp/kmz_directory/#{self.id}.kmz"
        zf = ZipFileGenerator.new(directory_to_zip, output_file)
        zf.write()
        #send to S3
        s3 = Aws::S3::Resource.new
        obj = s3.bucket(ENV['S3_BUCKET']).object("uploads/kmz_directory/" + "#{self.id}.kmz")
        obj.upload_file("/tmp/kmz_directory/#{self.id}.kmz")
    end

    def download_project
        #tmp cleanup    
        #FileUtils.rm_r '/tmp'

        #delete target directory if exists
        if Dir.exist?("/tmp/#{self.id}") 
            FileUtils.remove_dir("/tmp/#{self.id}")
        end

        #create kmz_dir if needed
        if Dir.exist?("/tmp/kmz_directory") 
        else
           FileUtils.mkdir "/tmp/kmz_directory"  
        end

        #create target dir
        FileUtils.mkdir "/tmp/#{self.id}" 

        #download pics
        s3 = Aws::S3::Resource.new
        s3.bucket(ENV['S3_BUCKET']).object_versions({ prefix:"uploads/#{self.id}" }).each do |object|
            #get file name
            full_key = object.key
            file_name = full_key.to_s.split('/').last
            #save to /tmp
            object.get(response_target: "/tmp/#{self.id}/#{file_name}")
        end

    end

1 个答案:

答案 0 :(得分:1)

Heroku将网络请求限制为30秒。通常,长时间运行的进程是使用sidekiq或延迟的工作在工作人员上进行的。您的网络客户端可以每隔几秒钟轮询一次ProjectsController#show操作,当文件准备就绪时,该操作将呈现一个页面,该页面带有指向s3存储桶中的kml文件的链接。