ilovepdf 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|