使用这个DBIx::Class插件管理文件轻而易举

管理应用程序文件上传具有挑战性:存储、去重、检索和权限都需要处理。DBIx::Class::InflateColumn::FS通过处理文件的底层存储,简化了挑战,使得程序员可以专注于应用程序开发。让我们更深入地了解一下它是如何工作的。

要求

为了使用此示例,您需要从CPAN安装DBIx::Class::InflateColumn::FS。CPAN测试人员结果显示,它应该在包括Windows在内的所有平台上运行。如果您还没有,还需要DBIx::Class::Schema::LoaderFile::MimeInfo,以及SQLite3。要安装Perl模块,打开终端并输入

$ cpan DBIx::Class::InflateColumn::FS DBIx::Class::Schema::Loader File::MimeInfo

设置结果类

让我们创建一个用于处理文件上传的示例类。DBIx::Class将对象映射到数据库表,因此我们需要创建一个表示我们的文件上传对象的数据库表。这是创建上传表的SQL代码

create table upload (
    id          integer     primary key,
    file        text        not null,
    mime        text        not null
);

将代码保存到名为create_upload.sql的脚本中,并在命令行中运行它

$ sqlite3 MyApp.db < create_upload.sql

这将创建上传表。接下来,我们可以使用随DBIx::Class::Schema::Loader一起提供的“dbicdump”应用程序为我们创建基本的结果类

$ dbicdump MyApp::Schema dbi:SQLite:MyApp.db

在文本编辑器中打开新创建的MyApp/Schema/Result/Upload.pm,在“# DO NOT MODIFY …”行下面添加以下代码

use File::MimeInfo 'extensions';

__PACKAGE__->load_components("InflateColumn::FS");
__PACKAGE__->add_columns(
    "file",
    {   
        data_type      => 'TEXT',
        is_fs_column   => 1,
        fs_column_path => 'uploads',
    }   
);

sub extension { 
    my ($self) = @_;
    [ extensions($self->mime) ]->[0];
}

此代码在Upload类的“file”属性上启用了DBIx::Class::InflateColumn::FS插件。此外,我们还添加了一个名为“extension”的子程序,它将返回文件的扩展名。

创建上传

此脚本将创建一个上传对象

#!/usr/bin/env perl
use strict;
use warnings;
use MyApp::Schema;
use MIME::Types;
use lib '.';

open(my $file, '<', $ARGV[0]) or die $!; 

my $schema = MyApp::Schema->connect('dbi:SQLite:MyApp.db');

# Add the file to the database and file system
my $upload = $schema->resultset('Upload')->
        create({ file => $file,
                 mime => (MIME::Types->new->mimeTypeOf($ARGV[0])) });

将脚本保存为“create_upload.pl”,我们可以在终端中调用它,并传递我们想要保存的文件的文件路径

$ perl create_upload.pl perltricks_logo.png

仅通过创建对象,DBIx::Class::InflateColumn::FS就会将文件保存在我们的上传目录中。无需编写额外的代码来显式复制文件。

检索上传

此脚本将检索上传对象。DBIx::Class::InflateColumn::FS自动将“file”列扩展为Path::Class::File对象,这为我们提供了许多便利方法

#!/usr/bin/env perl
use strict;
use warnings;
use MyApp::Schema;
use lib '.';

my $schema = MyApp::Schema->connect('dbi:SQLite:MyApp.db');

# retrieve the upload
my $upload = $schema->resultset('Upload')->find(1);

# get the relative path
$upload->file->relative;

# get the absolute path
$upload->file->absolute;

# get the base filename
$upload->file->basename;

# get the mime type (image/png)
$upload->mime;

# get the file extension
$upload->extension;

# get a read filehandle
$upload->file->openr;

# get a write filehandle
$upload->file->openw;

# get an append filehandle
$upload->file->opena;

删除上传

DBIx::Class::InflateColumn::FS使得删除文件变得超级简单。只需在结果对象上调用delete即可从表和文件系统中删除它

#!/usr/bin/env perl
use strict;
use warnings;
use MyApp::Schema;
use lib '.';

my $schema = MyApp::Schema->connect('dbi:SQLite:MyApp.db');

# retrieve the upload
my $upload = $schema->resultset('Upload')->find(1);

# delete the file from the database and file system
$upload->delete;

结论

DBIx::Class::InflateColumn::FS作为现成的工具很有用,但在某些情况下表现得尤为出色。例如,如果您正在管理图像文件,存储原始高质量图像并在请求时动态调整图像大小是非常有益的。这样,您可以最小化磁盘使用,并在应用程序逻辑中保留调整图像所需的灵活性。

感谢Devin Austin,他的Catalyst advent calendar 文章是本文的有用来源。

喜欢这篇文章吗?帮助我们并推文关于它!

封面图像 © Cas


本文最初发布在PerlTricks.com上。

标签

David Farrell

David是一位专业的程序员,他经常推文博客关于代码和编程艺术。

浏览他们的文章

反馈

这篇文章有问题吗?请通过在GitHub上打开一个问题或拉取请求来帮助我们。