Class: Api2Convert::Upload::FileUploader

Inherits:
Object
  • Object
show all
Defined in:
lib/api2convert/upload/file_uploader.rb

Overview

Uploads a local file to a job's per-job upload server.

This step is intentionally hand-written — it is NOT described by the OpenAPI spec. It posts a multipart/form-data body (field file) to {job.server}/upload-file/{job.id} and authenticates with the per-job X-Oc-Token header — never the account API key. The body is streamed, so large files are not read into memory. Internal.

Instance Method Summary collapse

Constructor Details

#initialize(transport) ⇒ FileUploader

Returns a new instance of FileUploader.



16
17
18
# File 'lib/api2convert/upload/file_uploader.rb', line 16

def initialize(transport)
  @transport = transport
end

Instance Method Details

#upload(job, file, filename = nil) ⇒ Model::InputFile

Parameters:

  • job (Model::Job)

    a staged job (created with process: false).

  • file (String, Pathname, IO)

    a path, or an IO/StringIO of bytes.

Returns:



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/api2convert/upload/file_uploader.rb', line 23

def upload(job, file, filename = nil)
  if job.server.nil? || job.server.empty? || job.token.nil?
    raise Api2Convert::Error,
          "Cannot upload: the job has no upload server/token. " \
          "Create the job with process=false and upload before starting it."
  end

  io, resolved_name, opened = resolve(file, filename)
  seekable = io.respond_to?(:rewind)
  url = "#{job.server.sub(%r{/+\z}, "")}/upload-file/#{job.id}"
  token = job.token
  boundary = "----Api2Convert#{SecureRandom.hex(16)}"

  build = lambda do
    io.rewind if seekable
    body_stream, length = MultipartStream.build(boundary, "file", resolved_name, io)
    @transport.build_request(
      "POST", url,
      headers: {
        "X-Oc-Token" => token,
        "Content-Type" => "multipart/form-data; boundary=#{boundary}"
      },
      body_stream: body_stream,
      content_length: length
    )
  end

  begin
    response = @transport.send_request(build, replayable: seekable)
    Model::InputFile.from_hash(@transport.interpret(response))
  ensure
    opened&.close
  end
end