CombinePDF est un modèle Nifty, écrit en rubis pur, pour analyser les fichiers PDF et les combiner (fusionner) avec d'autres fichiers PDF, les filigraner ou les tamponner (tous en utilisant le format de fichier PDF et le code rubis pur).
J'ai décidé d'arrêter de maintenir ce joyau et d'espérer que quelqu'un pourrait prendre en charge les critiques de relations publiques et la maintenance de ce joyau (ou simplement ouvrir une fourche à succès).
J'ai écrit ce joyau parce que j'avais besoin de résoudre un problème avec les documents PDF existants de Bates.
Cependant, depuis 2014, je maintiens gratuitement le joyau et sans aucune raison, sauf que j'ai aimé le partager avec la communauté.
J'adore ce joyau, mais je ne peux pas continuer à le maintenir car j'ai mes propres projets pour me concentrer et j'ai besoin à la fois du temps et (plus important encore) de l'espace d'esprit.
Installer avec Ruby Gems:
gem install combine_pdf
Rundown rapide:
Lors de la lecture des formulaires PDF, certaines données de formulaire peuvent être perdues. J'ai essayé de résoudre ce problème au mieux de mes capacités, mais je ne suis pas sûr que tout fonctionne pour l'instant.
Lors de la combinaison des formulaires PDF, les données de formulaire peuvent être unifiées. Je ne pouvais pas résoudre ce problème parce que c'est ainsi que les formulaires PDF fonctionnent (remplir un champ remplit les données dans n'importe quel domaine du même nom), mais franchement, j'ai un peu aimé le problème ... c'est presque une fonctionnalité.
Lorsque vous unifiez les mêmes données TOC plus qu'une fois, l'une des références sera unifiée avec l'autre (ce qui signifie que si les pages se ressemblent, les deux références seront liées à la même page au lieu de lier à deux pages différentes). Vous pouvez résoudre ce problème en ajoutant du contenu aux pages avant de fusionner les fichiers PDF (c'est-à-dire Ajouter des zones de texte vides à toutes les pages).
Certains liens et données (liens URL et «destinations» nommés) sont stockés à la racine d'un PDF et ils ne sont pas liés à la page. Garder ces informations nécessite la fusion des objets PDF plutôt que leurs pages.
Certains liens seront perdus lorsque vous arrachez les pages des fichiers PDF et les fusionnant avec un autre PDF.
Certains fichiers PDF cryptés (généralement ceux que vous ne pouvez pas afficher sans mot de passe) échoueront tranquillement au lieu de bruyant. Si vous préférez choisir l'itinéraire bruyant, vous pouvez spécifier l'option raise_on_encrypted
à l'aide de CombinePDF.load(pdf_file, raise_on_encrypted: true)
qui augmentera un CombinePDF::EncryptionError
.
Parfois, le CombinePDF soulèvera une exception même si le PDF pouvait être analysé (c'est-à-dire lorsque le contenu facultatif PDF existe) ... Je trouve mieux de se tromper du côté de la prudence, bien que pour le contenu en option PDFS, une exception est évitable en utilisant CombinePDF.load(pdf_file, allow_optional_content: true)
.
Le GEM CombinePDF exécute du code récursif pour analyser et formater les fichiers PDF. Par conséquent, les fichiers PDF qui ont des objets fortement imbriqués, ainsi que ceux qui sont combinés d'une manière qui entraîne une nidification cyclique, pourrait exploser la pile - entraînant une exception ou une défaillance du programme.
Combinepdf est écrit nativement dans Ruby et devrait (vraisemblablement) fonctionner sur toutes les plates-formes Ruby qui suivent la compatibilité Ruby 2.0.
Cependant, les fichiers PDF sont des créatures assez complexes et aucune garantie n'est fournie.
Par exemple, les formulaires PDF sont connus pour avoir des problèmes et des données de formulaire peuvent être perdues lors de la tentative de combinaison des PDF avec des données de formulaire remplies (également, les formulaires sont des objets globaux, pas spécifiques à la page, il faut donc combiner l'ensemble du PDF pour toutes les données à avoir une chance d'être préservé).
Il en va de même pour les liaisons PDF et la table des matières, qui ont toutes des attributs globaux et pourraient être corrompus ou perdus lors de la combinaison des données PDF.
Si cette bibliothèque provoque une perte de données ou brûle votre maison, je ne suis pas à blâmer - comme indiqué par la licence MIT. Cela étant dit, j'utilise joyeusement la bibliothèque après avoir testé contre différentes solutions.
Pour combiner des fichiers PDF (ou des données):
pdf = CombinePDF . new
pdf << CombinePDF . load ( "file1.pdf" ) # one way to combine, very fast.
pdf << CombinePDF . load ( "file2.pdf" )
pdf . save "combined.pdf"
Ou même une doublure:
( CombinePDF . load ( "file1.pdf" ) << CombinePDF . load ( "file2.pdf" ) << CombinePDF . load ( "file3.pdf" ) ) . save ( "combined.pdf" )
Vous pouvez également ajouter des pages étranges ou même:
pdf = CombinePDF . new
i = 0
CombinePDF . load ( "file.pdf" ) . pages . each do | page |
i += 1
pdf << page if i . even?
end
pdf . save "even_pages.pdf"
Notez que l'ajout de toutes les pages une par un est plus lente puis l'ajout de tout le fichier.
Pour ajouter du contenu aux pages PDF existantes, importez d'abord le nouveau contenu à partir d'un fichier PDF existant. Après cela, ajoutez le contenu à chacune des pages de votre PDF existant.
Dans cet exemple, nous ajouterons un logo d'entreprise à chaque page:
company_logo = CombinePDF . load ( "company_logo.pdf" ) . pages [ 0 ]
pdf = CombinePDF . load "content_file.pdf"
pdf . pages . each { | page | page << company_logo } # notice the << operator is on a page and not a PDF object.
pdf . save "content_with_logo.pdf"
Remarquez que l'opérateur << est sur une page et non un objet PDF. L'opérateur << agit différemment sur les objets PDF et sur les pages.
L'opérateur << fait par défaut pour sécuriser l'injection en renommant les références pour éviter les conflics. Pour la superposition des pages à l'aide de données compressées qui pourraient ne pas être modifiables (en raison d'un support de filtre limité), vous pouvez utiliser:
pdf . pages ( nil , false ) . each { | page | page << stamp_page }
L'ajout de numéros de page à un objet ou un fichier PDF est aussi simple que possible:
pdf = CombinePDF . load "file_to_number.pdf"
pdf . number_pages
pdf . save "file_with_numbering.pdf"
La numérotation peut être effectuée avec de nombreuses options différentes, avec des formations différents, avec ou sans objet de boîte, et même avec des valeurs d'opacité - voir la documentation.
Par exemple, si vous préférez placer le numéro de page en bas à droite de toutes les pages PDF, faites:
pdf . number_pages ( location : [ :bottom_right ] )
Comme autre exemple, les tirets autour du nombre sont supprimés et une boîte est placée autour de lui. La numérotation est semi-transparente et les 3 premières pages sont numérotées à l'aide de lettres (a, b, c) plutôt que de nombres:
# number first 3 pages as "a", "b", "c"
pdf . number_pages ( number_format : " %s " ,
location : [ :top , :bottom , :top_left , :top_right , :bottom_left , :bottom_right ] ,
start_at : "a" ,
page_range : ( 0 .. 2 ) ,
box_color : [ 0.8 , 0.8 , 0.8 ] ,
border_color : [ 0.4 , 0.4 , 0.4 ] ,
border_width : 1 ,
box_radius : 6 ,
opacity : 0.75 )
# number the rest of the pages as 4, 5, ... etc'
pdf . number_pages ( number_format : " %s " ,
location : [ :top , :bottom , :top_left , :top_right , :bottom_left , :bottom_right ] ,
start_at : 4 ,
page_range : ( 3 ..- 1 ) ,
box_color : [ 0.8 , 0.8 , 0.8 ] ,
border_color : [ 0.4 , 0.4 , 0.4 ] ,
border_width : 1 ,
box_radius : 6 ,
opacity : 0.75 )
pdf.number_pages(number_format: " %s ", location: :bottom_right, font_size: 44)
Le chargement des données PDF peut être effectué à partir du système de fichiers ou directement à partir de la mémoire.
Le chargement des données d'un fichier est facile:
pdf = CombinePDF . load ( "file.pdf" )
Vous pouvez également analyser les fichiers PDF à partir de la mémoire. Le chargement à partir de la mémoire est particulièrement efficace pour l'importation de données PDF reçus via Internet ou à partir d'une bibliothèque de création différente comme la crevette:
pdf_data = prawn_pdf_document . render # Import PDF data from Prawn
pdf = CombinePDF . parse ( pdf_data )
L'utilisation parse
est également efficace lors du chargement des données à partir d'un emplacement distant, en contournant le besoin de fichiers temporaires inutiles. Par exemple:
require 'combine_pdf'
require 'net/http'
url = "https://example.com/my.pdf"
pdf = CombinePDF . parse Net :: HTTP . get_response ( URI . parse ( url ) ) . body
De même, le chargement et l'analyse, le rendu peut également être effectué soit à la mémoire ou à un fichier.
Vous pouvez publier une chaîne de données PDF à l'aide de .to_pdf
. Par exemple, pour permettre à un utilisateur de télécharger le PDF à partir d'une application Rails ou d'une application Plezi:
# in a controller action
send_data combined_file . to_pdf , filename : "combined.pdf" , type : "application/pdf"
Dans Sinatra:
# in your path's block
status 200
body combined_file . to_pdf
headers 'content-type' => "application/pdf"
Si vous préférez enregistrer les données PDF dans un fichier, vous pouvez toujours utiliser la méthode save
comme nous l'avons fait dans nos exemples précédents.
Certains fichiers PDF contiennent des sections de contenu en option qui ne peuvent pas toujours être fusionnées de manière fiable. Par défaut, une exception est soulevée si l'un de ces fichiers est détecté. Vous pouvez éventuellement transmettre un paramètre allow_optional_content
au PDFParser.new
, CombinePDF.load
et CombinePDF.parse
Méthodes:
new_pdf = CombinePDF . new
new_pdf << CombinePDF . load ( pdf_file , allow_optional_content : true )
attachments . each { | att | new_pdf << CombinePDF . load ( att , allow_optional_content : true ) }
Vous pouvez voir une démo pour un "Bates Stumping Web-App" et lire son code. Bonne chance :)
Certains fichiers PDF sont cryptés et certains sont compressés (l'utilisation des filtres) ...
Il y a très peu de prise en charge des fichiers chiffrés et une prise en charge très basique et limitée pour les fichiers compressés.
J'ai besoin d'aide avec ça.
Si vous souhaitez aider avec le code, sachez:
Je suis un plus passe-passe-passe le plus savant dans l'âme. La documentation fait défaut et les commentaires dans le code sont de mauvaises lignes de guidage.
Le code lui-même devrait être très simple, mais n'hésitez pas à demander ce que vous voulez.
Stefan Leitner (@ SLe1Tner) a écrit le code de fusion des PDF prenant en charge les PDF qui contiennent un TOC.
Caige Nichols a écrit un incroyable joyau RC4 que j'ai utilisé dans mon code.
Je voulais installer la gemme, mais j'ai eu des problèmes avec Internet et j'ai fini par copier le code lui-même dans le fichier de classe combinée_pdf_decrypt.
Le crédit à sa merveilleuse est accordé ici. Veuillez respecter sa licence et le droit d'auteur ... et le mien.
Mit
Vous pouvez consulter la page GitHub Issues et voir les balises "Help Wanted".
Si vous songez à des dons ou à m'envoyer de l'argent - pas besoin. Ce projet peut se maintenir sans votre argent.
Ce dont ce projet a besoin, c'est du temps donné par les développeurs qui se soucient de la maintenir à jour et réparent toutes les erreurs de documentation ou les problèmes qu'ils remarquent ... après avoir dit, des cadeaux (tels que du café gratuit ou des cartes-cadeaux iTunes) sont toujours amusants. Mais je pense qu'il y a ceux qui en ont réellement besoin qui bénéficieront davantage de votre générosité.