ilovepdf 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.editorconfig +12 -0
- data/.gitignore +14 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +142 -0
- data/Rakefile +6 -0
- data/bin/console +17 -0
- data/bin/setup +8 -0
- data/ilovepdf.gemspec +35 -0
- data/lib/ilovepdf.rb +36 -0
- data/lib/ilovepdf/errors.rb +51 -0
- data/lib/ilovepdf/file.rb +36 -0
- data/lib/ilovepdf/ilovepdf.rb +142 -0
- data/lib/ilovepdf/response.rb +36 -0
- data/lib/ilovepdf/task.rb +195 -0
- data/lib/ilovepdf/tool/compress.rb +20 -0
- data/lib/ilovepdf/tool/imagepdf.rb +27 -0
- data/lib/ilovepdf/tool/merge.rb +13 -0
- data/lib/ilovepdf/tool/officepdf.rb +13 -0
- data/lib/ilovepdf/tool/pagenumber.rb +40 -0
- data/lib/ilovepdf/tool/pdfa.rb +26 -0
- data/lib/ilovepdf/tool/pdfjpg.rb +22 -0
- data/lib/ilovepdf/tool/protect.rb +13 -0
- data/lib/ilovepdf/tool/repair.rb +12 -0
- data/lib/ilovepdf/tool/rotate.rb +12 -0
- data/lib/ilovepdf/tool/split.rb +35 -0
- data/lib/ilovepdf/tool/unlock.rb +12 -0
- data/lib/ilovepdf/tool/watermark.rb +49 -0
- data/lib/ilovepdf/version.rb +3 -0
- data/samples/compress_advanced.rb +25 -0
- data/samples/compress_basic.rb +14 -0
- data/samples/merge_advanced.rb +22 -0
- data/samples/merge_basic.rb +18 -0
- data/samples/pdfa_advanced.rb +21 -0
- data/samples/pdfa_basic.rb +17 -0
- data/samples/repair_advanced.rb +21 -0
- data/samples/repair_basic.rb +17 -0
- data/samples/rotate_advanced.rb +21 -0
- data/samples/rotate_basic.rb +17 -0
- data/samples/split_advanced.rb +32 -0
- data/samples/split_advanced_merge.rb +30 -0
- data/samples/split_basic.rb +17 -0
- data/samples/try_catch_errors.rb +46 -0
- data/samples/unlock_advanced.rb +21 -0
- data/samples/unlock_basic.rb +17 -0
- data/samples/watermark_advanced.rb +57 -0
- data/samples/watermark_basic.rb +20 -0
- data/uploads/sample_pdf.pdf +0 -0
- metadata +209 -0
@@ -0,0 +1,36 @@
|
|
1
|
+
module Ilovepdf
|
2
|
+
class Response
|
3
|
+
attr_accessor :response
|
4
|
+
|
5
|
+
def initialize(response)
|
6
|
+
raise ArgumentError.new('Argument must be of type \'RestClient::Response\'') unless response.is_a? ::RestClient::Response
|
7
|
+
self.response = response
|
8
|
+
end
|
9
|
+
|
10
|
+
def headers
|
11
|
+
self.response.headers
|
12
|
+
end
|
13
|
+
|
14
|
+
def body
|
15
|
+
return @body if @body
|
16
|
+
is_json = (/application\/json/i =~ self.response.headers[:content_type]) != nil
|
17
|
+
if is_json
|
18
|
+
@body ||= JSON.parse(self.response.body)
|
19
|
+
else
|
20
|
+
@body = self.response.body
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def raw_body
|
25
|
+
self.response.body
|
26
|
+
end
|
27
|
+
|
28
|
+
def code
|
29
|
+
self.response.code
|
30
|
+
end
|
31
|
+
|
32
|
+
def success?
|
33
|
+
self.response.code.to_s[0] == '2'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,195 @@
|
|
1
|
+
module Ilovepdf
|
2
|
+
class Task < Ilovepdf
|
3
|
+
attr_accessor :task_id, :tool, :packaged_filename, :output_filename,
|
4
|
+
:ignore_errors, :ignore_password, :try_pdf_repair
|
5
|
+
|
6
|
+
API_PARAMS = []
|
7
|
+
|
8
|
+
def initialize(public_key, secret_key)
|
9
|
+
super(public_key, secret_key)
|
10
|
+
response = perform_create_request
|
11
|
+
self.worker_server = 'https://' + response.body['server']
|
12
|
+
self.task_id = response.body['task']
|
13
|
+
|
14
|
+
# Assign default values
|
15
|
+
self.ignore_errors = true
|
16
|
+
self.ignore_password = true
|
17
|
+
self.try_pdf_repair = true
|
18
|
+
end
|
19
|
+
|
20
|
+
def assign_meta_value(key, value)
|
21
|
+
meta_values[key] = value
|
22
|
+
end
|
23
|
+
|
24
|
+
def files
|
25
|
+
@files ||= []
|
26
|
+
end
|
27
|
+
|
28
|
+
def add_file(filepath)
|
29
|
+
raise ArgumentError.new("No file exists in '#{filepath}'") unless ::File.exist?(filepath)
|
30
|
+
file = perform_upload_request(filepath)
|
31
|
+
files << file
|
32
|
+
files.last
|
33
|
+
end
|
34
|
+
|
35
|
+
def add_file_from_url(url)
|
36
|
+
file = perform_upload_url_request(url)
|
37
|
+
files << file
|
38
|
+
files.last
|
39
|
+
end
|
40
|
+
|
41
|
+
def download(path=nil)
|
42
|
+
download_file(path)
|
43
|
+
end
|
44
|
+
|
45
|
+
# [API Methods] Actions on task
|
46
|
+
|
47
|
+
def status
|
48
|
+
http_response = query_task_status(worker_server,task_id)
|
49
|
+
end
|
50
|
+
|
51
|
+
def execute
|
52
|
+
perform_process_request
|
53
|
+
end
|
54
|
+
|
55
|
+
def delete!
|
56
|
+
send_request('delete', 'task/' + self.task_id)
|
57
|
+
end
|
58
|
+
|
59
|
+
def delete_file(file)
|
60
|
+
raise Error.new("File was already deleted") if file.deleted?
|
61
|
+
file_was_found = files.find{|f| f.server_filename == file.server_filename }
|
62
|
+
raise Error.new("File to delete not found") if !file_was_found
|
63
|
+
response = perform_deletefile_request(file)
|
64
|
+
if response.success?
|
65
|
+
file.mark_as_deleted
|
66
|
+
new_files = files.reject{|f| f.server_filename == file.server_filename }
|
67
|
+
send(:files=, new_files)
|
68
|
+
else
|
69
|
+
raise ApiError.new(response, custom_msg: "No error ocurred but response was not successful when deleting the desired file")
|
70
|
+
end
|
71
|
+
true
|
72
|
+
end
|
73
|
+
|
74
|
+
def enable_file_encryption(enable, new_encrypt_key = nil)
|
75
|
+
raise Error.new("Encryption mode cannot be assigned after uploading the files") if files.size > 0
|
76
|
+
super(enable, new_encrypt_key)
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
# set meta values as http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/pdf_reference_1-7.pdf (page 844)
|
82
|
+
def meta_values
|
83
|
+
@meta_values ||= {}
|
84
|
+
end
|
85
|
+
|
86
|
+
def files=(new_array_of_files)
|
87
|
+
@files = new_array_of_files
|
88
|
+
end
|
89
|
+
|
90
|
+
def download_file path
|
91
|
+
response = perform_filedownload_request
|
92
|
+
content_disposition = response.headers[:content_disposition]
|
93
|
+
|
94
|
+
if match_data = /filename\*\=utf-8\'\'([\W\w]+)/.match(content_disposition)
|
95
|
+
filename = URI.unescape(match_data[1].gsub('"', ''))
|
96
|
+
else
|
97
|
+
match_data = / .*filename=\"([\W\w]+)\"/.match(content_disposition)
|
98
|
+
filename = match_data[1].gsub('"', '')
|
99
|
+
end
|
100
|
+
|
101
|
+
if path
|
102
|
+
path = Pathname.new(path).to_s if path.is_a?(Pathname)
|
103
|
+
path.chop! if path.end_with? '/'
|
104
|
+
else
|
105
|
+
path = '.'
|
106
|
+
end
|
107
|
+
destination = "#{path}/#{filename}"
|
108
|
+
::File.open(destination, 'wb'){|file| file.write(response.raw_body) }
|
109
|
+
file = response.raw_body
|
110
|
+
true
|
111
|
+
end
|
112
|
+
|
113
|
+
# [HTTP request methods]
|
114
|
+
def perform_deletefile_request(file)
|
115
|
+
body = {
|
116
|
+
task: self.task_id,
|
117
|
+
server_filename: file.server_filename,
|
118
|
+
v: API_VERSION
|
119
|
+
}
|
120
|
+
response = send_request('post', 'upload/delete', body: body)
|
121
|
+
end
|
122
|
+
|
123
|
+
def perform_filedownload_request
|
124
|
+
response = send_request('get', 'download/' + self.task_id, body: {v: API_VERSION})
|
125
|
+
end
|
126
|
+
|
127
|
+
def perform_process_request
|
128
|
+
body = {
|
129
|
+
task: self.task_id,
|
130
|
+
tool: self.tool,
|
131
|
+
packaged_filename: self.packaged_filename,
|
132
|
+
output_filename: self.output_filename,
|
133
|
+
ignore_errors: self.ignore_errors,
|
134
|
+
ignore_password: self.ignore_password,
|
135
|
+
try_pdf_repair: self.try_pdf_repair,
|
136
|
+
meta: meta_values,
|
137
|
+
v: API_VERSION,
|
138
|
+
}.merge(file_submit_params)
|
139
|
+
.merge(extract_api_params)
|
140
|
+
|
141
|
+
response = send_request('post', 'process', body: body)
|
142
|
+
response
|
143
|
+
end
|
144
|
+
|
145
|
+
def perform_create_request
|
146
|
+
request_opts = {
|
147
|
+
body: {v: API_VERSION}
|
148
|
+
}
|
149
|
+
response = send_request('get', 'start/' + self.tool.to_s, request_opts)
|
150
|
+
end
|
151
|
+
|
152
|
+
def perform_upload_request filepath
|
153
|
+
request_opts = {
|
154
|
+
body: {
|
155
|
+
multipart: true,
|
156
|
+
v: API_VERSION,
|
157
|
+
task: self.task_id,
|
158
|
+
file: ::File.new(filepath, 'rb')
|
159
|
+
}
|
160
|
+
}
|
161
|
+
# filepath
|
162
|
+
response = send_request('post', 'upload', request_opts)
|
163
|
+
File.new(response.body['server_filename'], Pathname.new(filepath).basename.to_s)
|
164
|
+
end
|
165
|
+
|
166
|
+
def perform_upload_url_request url
|
167
|
+
request_opts = {
|
168
|
+
body: {
|
169
|
+
multipart: true,
|
170
|
+
v: API_VERSION,
|
171
|
+
task: self.task_id,
|
172
|
+
cloud_file: url
|
173
|
+
}
|
174
|
+
}
|
175
|
+
response = send_request('post', 'upload', request_opts)
|
176
|
+
File.new(response.body['server_filename'], Pathname.new(url).basename.to_s)
|
177
|
+
end
|
178
|
+
|
179
|
+
def file_submit_params
|
180
|
+
h = {files:{}}
|
181
|
+
files.each_with_index do |f, i|
|
182
|
+
h[:files][i.to_s] = f.file_options
|
183
|
+
end
|
184
|
+
h
|
185
|
+
end
|
186
|
+
|
187
|
+
def extract_api_params
|
188
|
+
{}.tap do |h|
|
189
|
+
self.class::API_PARAMS.each{ |param_name|
|
190
|
+
h[param_name] = send(param_name)
|
191
|
+
}
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Ilovepdf
|
2
|
+
module Tool
|
3
|
+
class Compress < ::Ilovepdf::Task
|
4
|
+
API_PARAMS = [:compression_level]
|
5
|
+
attr_accessor *API_PARAMS
|
6
|
+
|
7
|
+
COMPRESSION_LEVEL_VALUES = ["extreme", "recommended", "low"]
|
8
|
+
|
9
|
+
def initialize(public_key, secret_key)
|
10
|
+
self.tool = :compress
|
11
|
+
super(public_key, secret_key)
|
12
|
+
end
|
13
|
+
|
14
|
+
def compression_level= level
|
15
|
+
raise Errors::ArgumentEnumError.new(COMPRESSION_LEVEL_VALUES) unless COMPRESSION_LEVEL_VALUES.include? level
|
16
|
+
@compression_level = level
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Ilovepdf
|
2
|
+
module Tool
|
3
|
+
class Imagepdf < ::Ilovepdf::Task
|
4
|
+
API_PARAMS = [:orientation, :margin, :pagesize, :merge_after]
|
5
|
+
attr_accessor *API_PARAMS
|
6
|
+
|
7
|
+
ORIENTATION_VALUES = ['portrait', 'landscape']
|
8
|
+
PAGESIZE_VALUES = ['fit', 'A4', 'letter']
|
9
|
+
|
10
|
+
def initialize(public_key, secret_key)
|
11
|
+
self.tool = :imagepdf
|
12
|
+
self.merge_after = true
|
13
|
+
super(public_key, secret_key)
|
14
|
+
end
|
15
|
+
|
16
|
+
def orientation=(new_val)
|
17
|
+
raise Errors::ArgumentEnumError.new(ORIENTATION_VALUES) unless ORIENTATION_VALUES.include? new_val
|
18
|
+
@orientation = new_val
|
19
|
+
end
|
20
|
+
|
21
|
+
def pagesize=(new_val)
|
22
|
+
raise Errors::ArgumentEnumError.new(PAGESIZE_VALUES) unless PAGESIZE_VALUES.include? new_val
|
23
|
+
@pagesize = new_val
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Ilovepdf
|
2
|
+
module Tool
|
3
|
+
class Pagenumber < ::Ilovepdf::Task
|
4
|
+
API_PARAMS = [
|
5
|
+
:facing_pages, :first_cover, :pages, :starting_number, :vertical_position,
|
6
|
+
:horizontal_position, :vertical_position_adjustment, :horizontal_position_adjustment,
|
7
|
+
:font_family, :font_style, :font_size, :font_color, :text
|
8
|
+
]
|
9
|
+
|
10
|
+
attr_accessor *API_PARAMS
|
11
|
+
|
12
|
+
VERTICAL_POSITION_VALUES = ['bottom', 'top']
|
13
|
+
HORIZONTAL_POSITION_VALUES = ['left', 'middle', 'right']
|
14
|
+
FONT_FAMILY_VALUES = [ 'Arial', 'Arial Unicode MS', 'Verdana', 'Courier',
|
15
|
+
'Times New Roman', 'Comic Sans MS',
|
16
|
+
'WenQuanYi Zen Hei', 'Lohit Marathi'
|
17
|
+
]
|
18
|
+
|
19
|
+
def initialize(public_key, secret_key)
|
20
|
+
self.tool = :pagenumber
|
21
|
+
super(public_key, secret_key)
|
22
|
+
end
|
23
|
+
|
24
|
+
def vertical_position=(new_val)
|
25
|
+
raise Errors::ArgumentEnumError.new(VERTICAL_POSITION_VALUES) unless VERTICAL_POSITION_VALUES.include? new_val
|
26
|
+
@vertical_position = new_val
|
27
|
+
end
|
28
|
+
|
29
|
+
def horizontal_position=(new_val)
|
30
|
+
raise Errors::ArgumentEnumError.new(HORIZONTAL_POSITION_VALUES) unless HORIZONTAL_POSITION_VALUES.include? new_val
|
31
|
+
@horizontal_position = new_val
|
32
|
+
end
|
33
|
+
|
34
|
+
def font_family=(new_val)
|
35
|
+
raise Errors::ArgumentEnumError.new(FONT_FAMILY_VALUES) unless FONT_FAMILY_VALUES.include? new_val
|
36
|
+
@font_family = new_val
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Ilovepdf
|
2
|
+
module Tool
|
3
|
+
class Pdfa < ::Ilovepdf::Task
|
4
|
+
API_PARAMS = [:conformance]
|
5
|
+
attr_accessor *API_PARAMS
|
6
|
+
|
7
|
+
CONFORMANCE_VALUES = ['pdfa-1b', 'pdfa-1a', 'pdfa-2b', 'pdfa-2u',
|
8
|
+
'pdfa-2a', 'pdfa-3b', 'pdfa-3u', 'pdfa-3a'
|
9
|
+
]
|
10
|
+
|
11
|
+
def initialize(public_key, secret_key)
|
12
|
+
self.tool = :pdfa
|
13
|
+
super(public_key, secret_key)
|
14
|
+
end
|
15
|
+
|
16
|
+
def conformance= new_val
|
17
|
+
raise Errors::ArgumentEnumError.new(CONFORMANCE_VALUES) unless CONFORMANCE_VALUES.include? new_val
|
18
|
+
@conformance = new_val
|
19
|
+
end
|
20
|
+
|
21
|
+
def conformance
|
22
|
+
@conformance ||= 'default'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Ilovepdf
|
2
|
+
module Tool
|
3
|
+
class Pdfjpg < ::Ilovepdf::Task
|
4
|
+
API_PARAMS = [:mode]
|
5
|
+
|
6
|
+
MODE_VALUES = ['pages', 'extract']
|
7
|
+
|
8
|
+
def initialize(public_key, secret_key)
|
9
|
+
self.tool = :pdfjpg
|
10
|
+
super(public_key, secret_key)
|
11
|
+
end
|
12
|
+
|
13
|
+
def mode=(new_val)
|
14
|
+
raise Errors::ArgumentEnumError.new(MODE_VALUES) unless MODE_VALUES.include?(new_val)
|
15
|
+
@mode = new_val
|
16
|
+
end
|
17
|
+
def mode
|
18
|
+
@mode
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Ilovepdf
|
2
|
+
module Tool
|
3
|
+
class Split < ::Ilovepdf::Task
|
4
|
+
API_PARAMS = [:ranges, :split_mode, :fixed_range, :remove_pages, :merge_after]
|
5
|
+
attr_accessor *API_PARAMS
|
6
|
+
|
7
|
+
def initialize(public_key, secret_key)
|
8
|
+
self.tool = :split
|
9
|
+
super(public_key, secret_key)
|
10
|
+
end
|
11
|
+
|
12
|
+
def fixed_range=(range=1)
|
13
|
+
@split_mode = 'fixed_range'
|
14
|
+
@fixed_range = range
|
15
|
+
end
|
16
|
+
|
17
|
+
def remove_pages=(pages)
|
18
|
+
@split_mode = 'remove_pages'
|
19
|
+
@remove_pages = pages
|
20
|
+
end
|
21
|
+
|
22
|
+
def ranges=(pages)
|
23
|
+
@split_mode = 'ranges'
|
24
|
+
@ranges = pages
|
25
|
+
end
|
26
|
+
|
27
|
+
def merge_after=(value)
|
28
|
+
@merge_after = value
|
29
|
+
end
|
30
|
+
def merge_after
|
31
|
+
@merge_after ||= false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|