Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 1dfb0798

Von Werner Hahn vor etwa 7 Jahren hinzugefügt

  • ID 1dfb079842fac9fb9b93b9988974383bf03f2ec1
  • Vorgänger 1e92b81c
  • Nachfolger f533d42b

Shopmodul: Fileuploader

Unterschiede anzeigen:

SL/Controller/FileUploader.pm
1
package SL::Controller::FileUploader;
2

  
3
use strict;
4
use parent qw(SL::Controller::Base);
5

  
6
use SL::DB::File;
7

  
8
use SL::Helper::Flash;
9
use SL::Locale::String;
10

  
11
use Rose::Object::MakeMethods::Generic
12
(
13
  'scalar --get_set_init' => [ qw(file) ],
14
);
15

  
16
#
17
# actions
18
#
19
sub action_test_page{
20
  my ($self) = @_;
21
  $self->render('fileuploader/test_page');
22
}
23

  
24
sub action_upload_form{
25
  my ($self) = @_;
26
  $self->file(SL::DB::File->new);
27
  $self->render('common/file_upload', {header => 0});
28
}
29

  
30
sub action_show_files {
31
  my ($self) = @_;
32

  
33

  
34
}
35

  
36
sub action_ajax_add_file{
37
  my ($self) = @_;
38
  $self->file( $::form->{id} ? SL::DB::File->new(id => $::form->{id})->load : SL::DB::File->new );
39
  $self->render('common/file_upload', { layout => 0}, data => $::form);
40
}
41

  
42

  
43
#
44
# helpers
45
#
46

  
47
sub validate_filetype {
48
  my ($self,$filename,$allowed_filetypes) = @_;
49

  
50
  my @errors;
51
  my($file,$filetype) = split /\./, $filename;
52
  my @file_types = split /\|/, $allowed_filetypes;
53

  
54
  if (!grep {$_ eq $filetype} @file_types) {
55
      push @errors, t8("Filetype not allowed");
56
  }
57
  return @errors
58
}
59

  
60
sub action_upload_form{
61
  my ($self) = @_;
62
  $self->file(SL::DB::File->new);
63
  $self->render('common/file_upload', {header => 0});
64
}
65

  
66
sub action_show_files {
67
  my ($self) = @_;
68

  
69

  
70
sub action_ajax_add_file{
71
  my ($self) = @_;
72
  $self->file(SL::DB::File->new);
73
  $self->render('common/file_upload', { layout => 0}, DATA => $::form);
74
}
75

  
76
sub action_ajax_upload_file{
77
  my ($self, %params) = @_;
78
  my $attributes                  = $::form->{ $::form->{form_prefix} } || die "Missing FormPrefix";
79
  $attributes->{trans_id}         = $::form->{id} || die "Missing ID";
80
  $attributes->{modul}            = $::form->{modul} || die "Missing Modul";
81
  $attributes->{filename}         = $::form->{FILENAME} || die "Missing Filename";
82
  $attributes->{title}            = $::form->{ $::form->{form_prefix} }->{title};
83
  $attributes->{description}      = $::form->{ $::form->{form_prefix} }->{description};
84
  my @image_types = ("jpg","tif","png");
85

  
86
  my @errors = $self->file(SL::DB::File->new(%{ $attributes }))->validate;
87
  return $self->js->error(@errors)->render($self) if @errors;
88

  
89
  $self->file->save;
90

  
91
  # TODO js call
92
  $self->render('fileuploader/test_page');
93
}
94

  
95
#
96
# helpers
97
#
98

  
99
sub init_file {
100
  return SL::DB::File->new(id => $::form->{id})->load;
101
}
102

  
103
1;
104
__END__
105

  
106
=pod
107

  
108
=encoding utf8
109

  
110
=head1 NAME
111

  
112
SL::Controller::FileUploader - Controller to manage fileuploads
113

  
114
=head1 SYNOPSIS
115

  
116
  use SL::Controller::FileUploader;
117

  
118
  # synopsis.. =>
119

  
120
=head1 DESCRIPTION
121

  
122
# longer description...
123

  
124

  
125
=head1 INTERFACE
126

  
127

  
128
=head1 DEPENDENCIES
129

  
130

  
131
=head1 SEE ALSO
132

  
133
=head1 AUTHOR
134

  
135
Werner Hahn E<lt>wh@futureworldsearch.netE<gt>
136

  
137
=cut
SL/DB/Helper/ThumbnailCreator.pm
1
package SL::DB::Helper::ThumbnailCreator;
2

  
3
use strict;
4

  
5
use Carp;
6
use GD;
7
use Image::Info;
8
use File::MimeInfo::Magic;
9
use List::MoreUtils qw(apply);
10
use List::Util qw(max);
11
use Rose::DB::Object::Util;
12

  
13
require Exporter;
14
our @ISA      = qw(Exporter);
15
our @EXPORT   = qw(file_create_thumbnail file_update_thumbnail file_probe_type file_update_type_and_dimensions);
16

  
17
# TODO PDFs and others like odt,txt,...
18
our %supported_mime_types = (
19
  'image/gif'  => { extension => 'gif', convert_to_png => 1, },
20
  'image/png'  => { extension => 'png' },
21
  'image/jpeg' => { extension => 'jpg' },
22
  'image/tiff' => { extension => 'tif'},
23
);
24

  
25
sub file_create_thumbnail {
26
  my ($self) = @_;
27
  croak "No picture set yet" if !$self->file_content;
28

  
29
  my $image            = GD::Image->new($self->file_content);
30
  my ($width, $height) = $image->getBounds;
31
  my $max_dim          = 64;
32
  my $curr_max         = max $width, $height, 1;
33
  my $factor           = $curr_max <= $max_dim ? 1 : $curr_max / $max_dim;
34
  my $new_width        = int($width  / $factor + 0.5);
35
  my $new_height       = int($height / $factor + 0.5);
36
  my $thumbnail        = GD::Image->new($new_width, $new_height);
37

  
38
  $thumbnail->copyResized($image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
39

  
40
  $self->thumbnail_img_content($thumbnail->png);
41
  $self->thumbnail_img_content_type('image/png');
42
  $self->thumbnail_img_width($new_width);
43
  $self->thumbnail_img_height($new_height);
44
  return 1;
45

  
46
}
47

  
48
sub file_update_thumbnail {
49
  my ($self) = @_;
50

  
51
  return 1 if !$self->file_content || !$self->file_content_type || !Rose::DB::Object::Util::get_column_value_modified($self, 'file_content');
52
  $self->file_create_thumbnail;
53
  return 1;
54
}
55

  
56
sub file_probe_type {
57
  my ($self) = @_;
58

  
59
  return (t8("No file uploaded yet")) if !$self->file_content;
60
  my $mime_type = File::MimeInfo::Magic::magic($self->file_content);
61

  
62
  my $info = Image::Info::image_info(\$self->{file_content});
63
  if (!$info || $info->{error} || !$info->{file_media_type} || !$supported_mime_types{ $info->{file_media_type} }) {
64
    $::lxdebug->warn("Image::Info error: " . $info->{error}) if $info && $info->{error};
65
    return (t8('Unsupported image type (supported types: #1)', join(' ', sort keys %supported_mime_types)));
66
  }
67

  
68
  $self->file_content_type($info->{file_media_type});
69
  $self->files_img_width($info->{width});
70
  $self->files_img_height($info->{height});
71
  $self->files_mtime(DateTime->now_local);
72

  
73
  $self->file_create_thumbnail;
74

  
75
  return ();
76
}
77

  
78
sub file_update_type_and_dimensions {
79
  my ($self) = @_;
80

  
81
  return () if !$self->file_content;
82
  return () if $self->file_content_type && $self->file_img_width && $self->file_img_height && !Rose::DB::Object::Util::get_column_value_modified($self, 'file_content');
83

  
84
  my @errors = $self->file_probe_type;
85
  return @errors if @errors;
86

  
87
  my $info = $supported_mime_types{ $self->file_content_type };
88
  if ($info->{convert_to_png}) {
89
    $self->file_content(GD::Image->new($self->file_content)->png);
90
    $self->file_content_type('image/png');
91
    $self->filename(apply { s/\.[^\.]+$//;  $_ .= '.png'; } $self->filename);
92
  }
93
  return ();
94
}
95

  
96
1;
97
__END__
98

  
99
=pod
100

  
101
=encoding utf8
102

  
103
=head1 NAME
104

  
105
SL::DB::Helper::ThumbnailCreator - DatabaseClass Helper for Fileuploads
106

  
107
=head1 SYNOPSIS
108

  
109
  use SL::DB::Helper::ThumbnailCreator;
110

  
111
  # synopsis...
112

  
113
=head1 DESCRIPTION
114

  
115
# longer description..
116
=head1 AUTHOR
117

  
118
Werner Hahn E<lt>wh@futureworldsearch.netE<gt>
119

  
120
=cut
121

  
122

  
123
=head1 INTERFACE
124

  
125

  
126
=head1 DEPENDENCIES
127

  
128

  
129
=head1 SEE ALSO
130

  
131

  
sql/Pg-upgrade2/files.sql
1 1
-- @tag: files
2 2
-- @description: Tabelle für Files
3 3
-- @charset: UTF-8
4
-- @depends: release_3_4_1 
4
-- @depends: release_3_4_1
5 5
CREATE TABLE files(
6 6
  id                          SERIAL PRIMARY KEY,
7 7
  object_type                 TEXT NOT NULL,    -- Tabellenname des Moduls z.B. customer, parts ... Fremdschlüssel Zusammen mit object_id
8 8
  object_id                   INTEGER NOT NULL, -- Fremdschlüssel auf die id der Tabelle aus Spalte object_type
9
  file_name                   TEXT NOT NULL,    
10
  file_type                   TEXT NOT NULL,    
9
  file_name                   TEXT NOT NULL,
10
  file_type                   TEXT NOT NULL,
11 11
  mime_type                   TEXT NOT NULL,
12
  source                      TEXT NOT NULL,    
12
  source                      TEXT NOT NULL,
13 13
  backend                     TEXT,
14
  backend_data                TEXT,         
14
  backend_data                TEXT,
15 15
  title                       varchar(45),
16
  description                 TEXT,             
16
  description                 TEXT,
17 17
  itime                       TIMESTAMP DEFAULT now(),
18 18
  mtime                       TIMESTAMP,
19 19
  CONSTRAINT valid_type CHECK (
20 20
             (object_type = 'credit_note') OR (object_type = 'invoice') OR (object_type = 'sales_order') OR (object_type = 'sales_quotation')
21 21
          OR (object_type = 'sales_delivery_order') OR (object_type = 'request_quotation') OR (object_type = 'purchase_order')
22
          OR (object_type = 'purchase_delivery_order') OR (object_type = 'purchase_invoice') 
23
          OR (object_type = 'vendor') OR (object_type = 'customer') OR (object_type = 'part') OR (object_type = 'gl_transaction') 
22
          OR (object_type = 'purchase_delivery_order') OR (object_type = 'purchase_invoice')
23
          OR (object_type = 'vendor') OR (object_type = 'customer') OR (object_type = 'part') OR (object_type = 'gl_transaction')
24 24
          OR (object_type = 'dunning') OR (object_type = 'dunning1') OR (object_type = 'dunning2') OR (object_type = 'dunning3')
25 25
          OR (object_type = 'draft') OR (object_type = 'statement'))
26 26
);
27

  
templates/webpages/common/file_upload.html
1
[%- USE LxERP -%][%- USE L -%][%- USE HTML -%][%- USE JavaScript -%][% USE Base64 %]
2
[% SET style="width: 500px" %]
3
[% SET id_base = "fileupload" %]
4
[% L.dump(DATA) %]
5
<form method="post" id="fileupload_form" method="POST" enctype="multipart/form-data">
6
 [% L.hidden_tag('form_prefix',                    id_base,         id=id_base _ '_form_prefix') %]
7
 [% L.hidden_tag('id',                             DATA.id, no_id=1) %]
8
 [% L.hidden_tag('modul',                          DATA.modul) %]
9

  
10
 <h2>
11
  [%- IF SELF.file.id %]
12
   [%- LxERP.t8("Edit file properties ", SELF.file.number) %]
13
  [%- ELSE %]
14
   [%- LxERP.t8("Add file to webdav") %]
15
  [%- END %]
16
 </h2>
17

  
18
 <table>
19
[% IF SELF.file.number %]
20
  <tr>
21
   <th align="right">[%- LxERP.t8("Number") %]:</th>
22
   <td>[% HTML.escape(SELF.file.number) %]</td>
23
  </tr>
24
[% END %]
25

  
26
  <tr>
27
   <th align="right">[%- LxERP.t8("Description") %]:</th>
28
   <td>[% L.input_tag(id_base _ '.description', SELF.file.description, style=style) %]</td>
29
  </tr>
30

  
31
  <tr>
32
   <th align="right">[%- LxERP.t8("Title") %]:</th>
33
   <td>[% L.input_tag(id_base _ '.title', SELF.file.title, style=style) %]</td>
34
  </tr>
35

  
36
[% IF SELF.file.file_content %]
37
  <tr>
38
   <th align="right">[%- LxERP.t8("File name") %]:</th>
39
   <td>[% HTML.escape(SELF.file.file_file_name) %]</td>
40
  </tr>
41

  
42
  <tr>
43
   <th align="right">[%- LxERP.t8("MIME type") %]:</th>
44
   <td>[% HTML.escape(SELF.file.file_content_type) %]</td>
45
  </tr>
46

  
47
  <tr>
48
   <th align="right">[%- LxERP.t8("Dimensions") %]:</th>
49
   <td>[% HTML.escape(SELF.file.file_width) %]x[% HTML.escape(SELF.file.file_height) %]</td>
50
  </tr>
51

  
52
  <tr>
53
   <th align="right">[%- LxERP.t8("Uploaded at") %]:</th>
54
   <td>[% HTML.escape(SELF.file.file_mtime.to_kivitendo(precision='second')) %]</td>
55
  </tr>
56
[% END %]
57

  
58
  <tr>
59
   <th align="right">[%- LxERP.t8("Select file to upload") %]:</th>
60
   <td>[% L.input_tag(id_base _ '.file_content', '', type='file') %]</td>
61
  </tr>
62
 </table>
63

  
64
 <p>
65
  [%- L.ajax_submit_tag('controller.pl?action=FileUploader/ajax_upload_file', '#fileupload_form', LxERP.t8('Save'), no_id=1) %]
66
  <a href="#" onclick="$('#jqueryui_popup_dialog').dialog('close');">[%- LxERP.t8("Cancel") %]</a>
67
 </p>
68

  
69
</form>
70

  
71
[% IF SELF.file.id %]
72
<h2>[% LxERP.t8("Current file") %]</h2>
73

  
74
<div>
75
 <img src="data:[% HTML.escape(SELF.file.file_content_type) %];base64,[% SELF.file.file_content.encode_base64 %]">
76
</div>
77
[% END %]
templates/webpages/fileuploader/test_page.html
1
[% USE L %]
2

  
3
<h1>Fileupload Testpage</h1>
4
<form method="post" id="fileupload" method="POST" enctype="multipart/form-data">
5
  <div id="testfunctions" style="width:50%; float:left; border:thin solid green">
6
    <div id="part_1" height="75px">
7
      Part: Select Part Where to store the file<br>
8
      [% L.part_picker('part_id1','',fat_set_item=1) %]<br>
9
      Part: <span id="change1"> </span> -- <span id="change2"></span><br>
10
      <div id="fileupload_button" style="display:none;">
11
        [% L.hidden_tag("id") %]
12
        [% L.hidden_tag("modul","part") %]
13
        [% L.button_tag("add_file(this.form.id.value,this.form.modul.value)", 'Fileupload') %]
14
      </div>
15
    </div>
16
    <div id="shoppart" height="75px">
17
      ShopPart: Select Part Where to store the file<br>
18
      [% L.part_picker('shoppart','',fat_set_item=1) %]<br>
19
      ShopPart: <span id="shoppartchange1"> </span> -- <span id="shoppartchange2"></span><br>
20
      <div id="shop_img_upload_button" style="display:none;">
21
        [% L.hidden_tag("shop_part_id") %]
22
        [% L.hidden_tag("shop_part_modul","shop_part") %]
23
        [% L.button_tag("add_file(this.form.shop_part_id.value,this.form.shop_part_modul.value)", 'Fileupload') %]
24
      </div>
25
    </div>
26
  </div>
27
</form>
28

  
29
<div id="testviews" style="width:50%; float:left; border:thin solid green">
30
  <div id="viewpart" height="75px">
31
  </div>
32
  <div id="viewshoppart" height="75px">
33
  </div>
34
</div>
35
<script type='text/javascript'>
36
<!--
37
 $('#part_id1').change(function() { $('#change1').html($('#part_id1').val()) });
38
 $('#part_id1').on('set_item:PartPicker', function(e,o) { $('#id').val(o.id);
39
                                                          $('#change2').html(o.id);
40
                                                          $('#fileupload_button').show();
41
                                                                  });
42
 $('#shoppart').change(function() { $('#shoppartchange1').html($('#shoppart').val()) });
43
 $('#shoppart').on('set_item:PartPicker', function(e,o) { $('#shop_part_id').val(o.id);
44
                                                          $('#shoppartchange2').html(o.id);
45
                                                          $('#shop_img_upload_button').show();
46
                                                                  });
47
function add_file(id,modul) {
48
  //var id = this.$('#part').val();
49
  kivi.popup_dialog({
50
        url :           'controller.pl?action=FileUploader/ajax_add_file',
51
        data:           'id=' + id + '&modul=' + modul,
52
        dialog:         { title: kivi.t8('File upload') }
53
  } );
54
  return true;
55
}
56
-->
57
</script>

Auch abrufbar als: Unified diff