pdfcrowd 1.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/pdfcrowd.rb +468 -0
- metadata +65 -0
data/lib/pdfcrowd.rb
ADDED
@@ -0,0 +1,468 @@
|
|
1
|
+
# Copyright (C) 2009-2011 pdfcrowd.com
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person
|
4
|
+
# obtaining a copy of this software and associated documentation
|
5
|
+
# files (the "Software"), to deal in the Software without
|
6
|
+
# restriction, including without limitation the rights to use,
|
7
|
+
# copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the
|
9
|
+
# Software is furnished to do so, subject to the following
|
10
|
+
# conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
# OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
24
|
+
require 'net/http'
|
25
|
+
require 'cgi'
|
26
|
+
|
27
|
+
|
28
|
+
module Pdfcrowd
|
29
|
+
# constants for setPageLayout()
|
30
|
+
SINGLE_PAGE, CONTINUOUS, CONTINUOUS_FACING = 1, 2, 3
|
31
|
+
|
32
|
+
# constants for setPageMode()
|
33
|
+
NONE_VISIBLE, THUMBNAILS_VISIBLE, FULLSCREEN = 1, 2, 3
|
34
|
+
|
35
|
+
# constants for setInitialPdfZoomType()
|
36
|
+
FIT_WIDTH, FIT_HEIGHT, FIT_PAGE = 1, 2, 3
|
37
|
+
|
38
|
+
|
39
|
+
#
|
40
|
+
# Thrown when an error occurs.
|
41
|
+
#
|
42
|
+
class Error < RuntimeError
|
43
|
+
attr_reader :http_code, :error
|
44
|
+
|
45
|
+
def initialize(error, http_code=nil)
|
46
|
+
super()
|
47
|
+
@http_code = http_code
|
48
|
+
@error = error
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_s()
|
52
|
+
@http_code ? "#{@http_code} - #{@error}" : @error
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
#
|
58
|
+
# Pdfcrowd API client.
|
59
|
+
#
|
60
|
+
class Client
|
61
|
+
|
62
|
+
#
|
63
|
+
# Client constructor.
|
64
|
+
#
|
65
|
+
# username -- your username at Pdfcrowd
|
66
|
+
# apikey -- your API key
|
67
|
+
#
|
68
|
+
def initialize(username, apikey)
|
69
|
+
useSSL(false)
|
70
|
+
@fields = {
|
71
|
+
'username' => username,
|
72
|
+
'key' => apikey
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
76
|
+
#
|
77
|
+
# Converts a web page.
|
78
|
+
#
|
79
|
+
# uri -- a web page URL
|
80
|
+
# outstream -- an object having method 'write(data)'; if nil then the
|
81
|
+
# return value is a string containing the PDF.
|
82
|
+
#
|
83
|
+
def convertURI(uri, outstream=nil)
|
84
|
+
return convert(outstream, 'uri', uri)
|
85
|
+
end
|
86
|
+
|
87
|
+
#
|
88
|
+
# Converts an in-memory html document.
|
89
|
+
#
|
90
|
+
# content -- a string containing an html document
|
91
|
+
# outstream -- an object having method 'write(data)'; if nil then the
|
92
|
+
# return value is a string containing the PDF.
|
93
|
+
#
|
94
|
+
def convertHtml(content, outstream=nil)
|
95
|
+
return convert(outstream, 'html', content)
|
96
|
+
end
|
97
|
+
|
98
|
+
#
|
99
|
+
# Converts an html file.
|
100
|
+
#
|
101
|
+
# fpath -- a path to an html file
|
102
|
+
# outstream -- an object having method 'write(data)'; if nil then the
|
103
|
+
# return value is a string containing the PDF.
|
104
|
+
#
|
105
|
+
def convertFile(fpath, outstream=nil)
|
106
|
+
return post_multipart(fpath, outstream)
|
107
|
+
end
|
108
|
+
|
109
|
+
#
|
110
|
+
# Returns the number of available conversion tokens.
|
111
|
+
#
|
112
|
+
def numTokens()
|
113
|
+
uri = @api_uri + 'user/%s/tokens/' % @fields['username']
|
114
|
+
response = call_api(uri, nil)
|
115
|
+
return Integer(response)
|
116
|
+
end
|
117
|
+
|
118
|
+
def useSSL(use_ssl)
|
119
|
+
@use_ssl = use_ssl
|
120
|
+
@api_uri = use_ssl ? HTTPS_API_URI : HTTP_API_URI
|
121
|
+
end
|
122
|
+
|
123
|
+
def setUsername(username)
|
124
|
+
@fields['username'] = username
|
125
|
+
end
|
126
|
+
|
127
|
+
def setApiKey(key)
|
128
|
+
@fields['key'] = key
|
129
|
+
end
|
130
|
+
|
131
|
+
def setPageWidth(value)
|
132
|
+
@fields['width'] = value
|
133
|
+
end
|
134
|
+
|
135
|
+
def setPageHeight(value)
|
136
|
+
@fields['height'] = value
|
137
|
+
end
|
138
|
+
|
139
|
+
def setHorizontalMargin(value)
|
140
|
+
@fields['hmargin'] = value
|
141
|
+
end
|
142
|
+
|
143
|
+
def setVerticalMargin(value)
|
144
|
+
@fields['vmargin'] = value
|
145
|
+
end
|
146
|
+
|
147
|
+
def setEncrypted(val=true)
|
148
|
+
@fields['encrypted'] = val
|
149
|
+
end
|
150
|
+
|
151
|
+
def setUserPassword(pwd)
|
152
|
+
@fields['user_pwd'] = pwd
|
153
|
+
end
|
154
|
+
|
155
|
+
def setOwnerPassword(pwd)
|
156
|
+
@fields['owner_pwd'] = pwd
|
157
|
+
end
|
158
|
+
|
159
|
+
def setNoPrint(val=true)
|
160
|
+
@fields['no_print'] = val
|
161
|
+
end
|
162
|
+
|
163
|
+
def setNoModify(val=true)
|
164
|
+
@fields['no_modify'] = val
|
165
|
+
end
|
166
|
+
|
167
|
+
def setNoCopy(val=true)
|
168
|
+
@fields['no_copy'] = val
|
169
|
+
end
|
170
|
+
|
171
|
+
def setPageLayout(value)
|
172
|
+
assert { value > 0 and value <= 3 }
|
173
|
+
@fields['page_layout'] = value
|
174
|
+
end
|
175
|
+
|
176
|
+
def setPageMode(value)
|
177
|
+
assert { value > 0 and value <= 3 }
|
178
|
+
@fields['page_mode'] = value
|
179
|
+
end
|
180
|
+
|
181
|
+
|
182
|
+
def setFooterText(value)
|
183
|
+
@fields['footer_text'] = value
|
184
|
+
end
|
185
|
+
|
186
|
+
def enableImages(value=true)
|
187
|
+
@fields['no_images'] = (not value)
|
188
|
+
end
|
189
|
+
|
190
|
+
def enableBackgrounds(value=true)
|
191
|
+
@fields['no_backgrounds'] = (not value)
|
192
|
+
end
|
193
|
+
|
194
|
+
def setHtmlZoom(value)
|
195
|
+
@fields['html_zoom'] = value
|
196
|
+
end
|
197
|
+
|
198
|
+
def enableJavaScript(value=true)
|
199
|
+
@fields['no_javascript'] = (not value)
|
200
|
+
end
|
201
|
+
|
202
|
+
def enableHyperlinks(value=true)
|
203
|
+
@fields['no_hyperlinks'] = (not value)
|
204
|
+
end
|
205
|
+
|
206
|
+
def setDefaultTextEncoding(value)
|
207
|
+
@fields['text_encoding'] = value
|
208
|
+
end
|
209
|
+
|
210
|
+
def usePrintMedia(value=true)
|
211
|
+
@fields['use_print_media'] = value
|
212
|
+
end
|
213
|
+
|
214
|
+
def setMaxPages(value)
|
215
|
+
@fields['max_pages'] = value
|
216
|
+
end
|
217
|
+
|
218
|
+
def enablePdfcrowdLogo(value=true)
|
219
|
+
@fields['pdfcrowd_logo'] = value
|
220
|
+
end
|
221
|
+
|
222
|
+
def setInitialPdfZoomType(value)
|
223
|
+
assert { value>0 and value<=3 }
|
224
|
+
@fields['initial_pdf_zoom_type'] = value
|
225
|
+
end
|
226
|
+
|
227
|
+
def setInitialPdfExactZoom(value)
|
228
|
+
@fields['initial_pdf_zoom_type'] = 4
|
229
|
+
@fields['initial_pdf_zoom'] = value
|
230
|
+
end
|
231
|
+
|
232
|
+
def setPdfScalingFactor(value)
|
233
|
+
@fields['pdf_scaling_factor'] = value
|
234
|
+
end
|
235
|
+
|
236
|
+
def setFooterHtml(value)
|
237
|
+
@fields['footer_html'] = value
|
238
|
+
end
|
239
|
+
|
240
|
+
def setFooterUrl(value)
|
241
|
+
@fields['footer_url'] = value
|
242
|
+
end
|
243
|
+
|
244
|
+
def setHeaderHtml(value)
|
245
|
+
@fields['header_html'] = value
|
246
|
+
end
|
247
|
+
|
248
|
+
def setHeaderUrl(value)
|
249
|
+
@fields['header_url'] = value
|
250
|
+
end
|
251
|
+
|
252
|
+
|
253
|
+
|
254
|
+
|
255
|
+
# ----------------------------------------------------------------------
|
256
|
+
#
|
257
|
+
# Private stuff
|
258
|
+
#
|
259
|
+
|
260
|
+
private
|
261
|
+
|
262
|
+
def create_http_obj()
|
263
|
+
if @use_ssl
|
264
|
+
require 'net/https' #apt-get install libopenssl-ruby
|
265
|
+
http = Net::HTTP.new($api_hostname, $api_https_port)
|
266
|
+
# OpenSSL::SSL::VERIFY_PEER fails here:
|
267
|
+
# ... certificate verify failed ...
|
268
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
269
|
+
http.use_ssl = @use_ssl
|
270
|
+
else
|
271
|
+
http = Net::HTTP.new($api_hostname, $api_http_port)
|
272
|
+
end
|
273
|
+
return http
|
274
|
+
end
|
275
|
+
|
276
|
+
def convert(out_stream, method, src)
|
277
|
+
uri = @api_uri + 'pdf/convert/%s/' % method
|
278
|
+
return call_api(uri, out_stream, src)
|
279
|
+
end
|
280
|
+
|
281
|
+
def call_api(uri, out_stream, src=nil)
|
282
|
+
data = encode_post_data({'src' => src})
|
283
|
+
url = URI.parse(uri)
|
284
|
+
req = Net::HTTP::Post.new(url.path)
|
285
|
+
req.set_form_data(data)
|
286
|
+
http = create_http_obj()
|
287
|
+
begin
|
288
|
+
res = http.start {|connection| connection.request(req) }
|
289
|
+
case res
|
290
|
+
when Net::HTTPSuccess, Net::HTTPRedirection
|
291
|
+
if out_stream
|
292
|
+
out_stream.write(res.body)
|
293
|
+
return out_stream
|
294
|
+
else
|
295
|
+
return res.body
|
296
|
+
end
|
297
|
+
else
|
298
|
+
raise Error.new(res.body, res.code)
|
299
|
+
end
|
300
|
+
rescue SystemCallError => why
|
301
|
+
raise Error.new("#{why}\n")
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
def encode_post_data(extra_data={})
|
306
|
+
result = extra_data.clone()
|
307
|
+
@fields.each { |key, val| result[key] = val if val }
|
308
|
+
result
|
309
|
+
end
|
310
|
+
|
311
|
+
def encode_multipart_post_data(filename)
|
312
|
+
boundary = '----------ThIs_Is_tHe_bOUnDary_$'
|
313
|
+
body = []
|
314
|
+
for field, value in @fields
|
315
|
+
body << '--' + boundary << 'Content-Disposition: form-data; name="%s"' % field << '' << value.to_s if value
|
316
|
+
end
|
317
|
+
# filename
|
318
|
+
body << '--' + boundary
|
319
|
+
body << 'Content-Disposition: form-data; name="src"; filename="%s"' % filename
|
320
|
+
mime_type = 'application/octet-stream'
|
321
|
+
body << 'Content-Type: ' + mime_type
|
322
|
+
body << ''
|
323
|
+
body << open(filename).read()
|
324
|
+
# finalize
|
325
|
+
body << '--' + boundary + '--'
|
326
|
+
body << ''
|
327
|
+
body = body.join("\r\n")
|
328
|
+
content_type = 'multipart/form-data; boundary=%s' % boundary
|
329
|
+
return content_type, body
|
330
|
+
end
|
331
|
+
|
332
|
+
def post_multipart(fpath, out_stream)
|
333
|
+
content_type, body = encode_multipart_post_data(fpath)
|
334
|
+
headers = { 'content-type' => content_type, 'content-length' => body.length.to_s }
|
335
|
+
http = create_http_obj()
|
336
|
+
begin
|
337
|
+
res = http.start {|connection| connection.post(API_SELECTOR_BASE + 'pdf/convert/html/', body, headers) }
|
338
|
+
case res
|
339
|
+
when Net::HTTPSuccess, Net::HTTPRedirection
|
340
|
+
if out_stream
|
341
|
+
out_stream.write(res.body)
|
342
|
+
return out_stream
|
343
|
+
else
|
344
|
+
return res.body
|
345
|
+
end
|
346
|
+
else
|
347
|
+
raise Error.new(res.body, res.code)
|
348
|
+
end
|
349
|
+
rescue SystemCallError => why
|
350
|
+
raise Error.new("#{why}\n")
|
351
|
+
end
|
352
|
+
return
|
353
|
+
end
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
|
358
|
+
def assert
|
359
|
+
raise "Assertion failed !" unless yield
|
360
|
+
end
|
361
|
+
|
362
|
+
|
363
|
+
$api_hostname = 'pdfcrowd.com'
|
364
|
+
$api_http_port = 80
|
365
|
+
$api_https_port = 443
|
366
|
+
|
367
|
+
|
368
|
+
API_SELECTOR_BASE = '/api/'
|
369
|
+
HTTP_API_URI = "http://#{$api_hostname}#{API_SELECTOR_BASE}"
|
370
|
+
HTTPS_API_URI = "https://#{$api_hostname}#{API_SELECTOR_BASE}"
|
371
|
+
|
372
|
+
|
373
|
+
|
374
|
+
# ---------------------------------------------------------------------------
|
375
|
+
#
|
376
|
+
# Test
|
377
|
+
#
|
378
|
+
|
379
|
+
if __FILE__ == $0
|
380
|
+
if ARGV.length < 2
|
381
|
+
print "usage: ruby pdfcrowd.rb username apikey [hostname [http-port https-port]]\n"
|
382
|
+
exit 1
|
383
|
+
end
|
384
|
+
|
385
|
+
if ARGV.length > 2
|
386
|
+
$api_hostname=ARGV[2]
|
387
|
+
end
|
388
|
+
|
389
|
+
if ARGV.length == 5
|
390
|
+
$api_http_port=ARGV[3]
|
391
|
+
$api_https_port=ARGV[4]
|
392
|
+
end
|
393
|
+
|
394
|
+
print "using %s ports %d %d\n" % [$api_hostname, $api_http_port, $api_https_port]
|
395
|
+
|
396
|
+
some_html="<html><body>Uploaded content!</body></html>"
|
397
|
+
Dir.chdir(File.dirname($0))
|
398
|
+
$test_dir = '../../test_files'
|
399
|
+
|
400
|
+
def out_stream(name, use_ssl)
|
401
|
+
fname = "#{$test_dir}/out/rb_client_#{name}"
|
402
|
+
if use_ssl
|
403
|
+
fname = fname + '_ssl'
|
404
|
+
end
|
405
|
+
return open(fname + '.pdf', 'wb')
|
406
|
+
end
|
407
|
+
|
408
|
+
client = Pdfcrowd::Client.new(ARGV[0], ARGV[1])
|
409
|
+
for use_ssl in [false, true]
|
410
|
+
client.useSSL(use_ssl)
|
411
|
+
begin
|
412
|
+
ntokens = client.numTokens()
|
413
|
+
client.convertURI('http://www.jagpdf.org/', out_stream('uri', use_ssl))
|
414
|
+
client.convertHtml(some_html, out_stream('content', use_ssl))
|
415
|
+
client.convertFile("#{$test_dir}/in/simple.html", out_stream('upload', use_ssl))
|
416
|
+
client.convertFile("#{$test_dir}/in/archive.tar.gz", out_stream('archive', use_ssl))
|
417
|
+
after_tokens = client.numTokens()
|
418
|
+
if ntokens-4 != after_tokens
|
419
|
+
raise RuntimeError, 'got unexpected number of tokens'
|
420
|
+
end
|
421
|
+
print "remaining tokens: %d \n" % client.numTokens()
|
422
|
+
rescue Pdfcrowd::Error => why
|
423
|
+
print 'FAILED: ', why
|
424
|
+
exit(1)
|
425
|
+
end
|
426
|
+
end
|
427
|
+
# test individual methods
|
428
|
+
begin
|
429
|
+
for method, arg in [[:setPageWidth, 500],
|
430
|
+
[:setPageHeight, -1],
|
431
|
+
[:setHorizontalMargin, 72],
|
432
|
+
[:setVerticalMargin, 72],
|
433
|
+
[:setEncrypted, true],
|
434
|
+
[:setUserPassword, 'userpwd'],
|
435
|
+
[:setOwnerPassword, 'ownerpwd'],
|
436
|
+
[:setNoPrint, true],
|
437
|
+
[:setNoModify, true],
|
438
|
+
[:setNoCopy, true],
|
439
|
+
[:setPageLayout, Pdfcrowd::CONTINUOUS],
|
440
|
+
[:setPageMode, Pdfcrowd::FULLSCREEN],
|
441
|
+
[:setFooterText, '%p/%n | source %u'],
|
442
|
+
[:enableImages, false],
|
443
|
+
[:enableBackgrounds, false],
|
444
|
+
[:setHtmlZoom, 300],
|
445
|
+
[:enableJavaScript, false],
|
446
|
+
[:enableHyperlinks, false],
|
447
|
+
[:setDefaultTextEncoding, 'iso-8859-1'],
|
448
|
+
[:usePrintMedia, true],
|
449
|
+
[:setMaxPages, 1],
|
450
|
+
[:enablePdfcrowdLogo, true],
|
451
|
+
[:setInitialPdfZoomType, Pdfcrowd::FIT_PAGE],
|
452
|
+
[:setInitialPdfExactZoom, 113],
|
453
|
+
[:setFooterHtml, '<b>bold</b> and <i>italic</i> <img src="http://pdfcrowd.com/static/images/logo175x30.png" />'],
|
454
|
+
[:setFooterUrl, 'http://google.com'],
|
455
|
+
[:setHeaderHtml, 'page %p out of %n'],
|
456
|
+
[:setHeaderUrl, 'http://google.com'],
|
457
|
+
[:setPdfScalingFactor, 0.5]]
|
458
|
+
client = Pdfcrowd::Client.new(ARGV[0], ARGV[1])
|
459
|
+
client.setVerticalMargin("1in")
|
460
|
+
client.send(method, arg)
|
461
|
+
client.convertFile("#{$test_dir}/in/simple.html", out_stream(method.id2name.downcase(), false))
|
462
|
+
end
|
463
|
+
rescue Pdfcrowd::Error => why
|
464
|
+
print 'FAILED: ', why
|
465
|
+
exit(1)
|
466
|
+
end
|
467
|
+
|
468
|
+
end
|
metadata
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pdfcrowd
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 55
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 8
|
9
|
+
- 0
|
10
|
+
version: 1.8.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Pdfcrowd Team
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-05-17 00:00:00 Z
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: It lets you easily convert web pages and raw HTML code to PDF in your Ruby applications.
|
22
|
+
email: info@pdfcrowd.com
|
23
|
+
executables: []
|
24
|
+
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files: []
|
28
|
+
|
29
|
+
files:
|
30
|
+
- lib/pdfcrowd.rb
|
31
|
+
homepage: https://pdfcrowd.com/html-to-pdf-api/
|
32
|
+
licenses: []
|
33
|
+
|
34
|
+
post_install_message:
|
35
|
+
rdoc_options: []
|
36
|
+
|
37
|
+
require_paths:
|
38
|
+
- lib
|
39
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
hash: 3
|
45
|
+
segments:
|
46
|
+
- 0
|
47
|
+
version: "0"
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
hash: 3
|
54
|
+
segments:
|
55
|
+
- 0
|
56
|
+
version: "0"
|
57
|
+
requirements: []
|
58
|
+
|
59
|
+
rubyforge_project:
|
60
|
+
rubygems_version: 1.7.2
|
61
|
+
signing_key:
|
62
|
+
specification_version: 3
|
63
|
+
summary: A client for the Pdfcrowd HTML to PDF API.
|
64
|
+
test_files: []
|
65
|
+
|