Перловый микрофреймворк Mojolicious::Lite умеет сам выдавать существующие файлы, но при этом не все из них получают верный тип содержимого Content-type
: некоторые файлы прикидываются обычными текстовыми (text/plain
), другие же вообще не имеют никакого типа — браузер такие файлы может воспринимать как угодно. В состав фреймворка входит модуль Mojolicious::Types, в котором определены MIME-типы для наиболее популярных (most common) расширений файлов:
appcache -> text/cache-manifest
atom -> application/atom+xml
bin -> application/octet-stream
css -> text/css
gif -> image/gif
gz -> application/x-gzip
htm -> text/html
html -> text/html;charset=UTF-8
ico -> image/x-icon
jpeg -> image/jpeg
jpg -> image/jpeg
js -> application/javascript
json -> application/json;charset=UTF-8
mp3 -> audio/mpeg
mp4 -> video/mp4
ogg -> audio/ogg
ogv -> video/ogg
pdf -> application/pdf
png -> image/png
rss -> application/rss+xml
svg -> image/svg+xml
txt -> text/plain;charset=UTF-8
webm -> video/webm
woff -> font/woff
woff2 -> font/woff2
xml -> application/xml,text/xml
zip -> application/zip
странно, но среди них нет ни одного, относящегося к офисным пакетам. На сайте Microsoft | Developer можно найти список типов — Office 2007 File Format MIME Types for HTTP Content Streaming. Чтобы не задумываться, какие же из этих типов брать, можно сохранить все — если есть какой-нибудь конфигурационный файл, он вполне подойдёт для хранения такого списка. В моём случае конфигурационные файлы обычно в формате YAML — это удобно.
---
# ... ещё какие-нибудь параметры
# MS Office types
types:
rtf: application/rtf
doc: application/msword
dot: application/msword
docx: application/vnd.openxmlformats-officedocument.wordprocessingml.document
Где-нибудь перед запуском приложения надо добавить типы (допустим, конфигурация приложения доступна через $config
)
while ( my ( $ext, $type ) = each %{ $config->{'types'} } ) {
app->types->type($ext => $type);
}
Правда, при выдаче файла тип его содержимого придётся всё-таки указать явно, иначе Mojolicious вернёт тип только для знакомых файлов, а для офисных будет undef
my $type = $self->app->types->mapping->{$ext}->[0];
if (my $asset = $self->app->static->file("/$path/$id.$ext")) {
$self->res->headers->content_type($type);
return $self->reply->asset($asset);
}
else {
return $self->reply->not_found;
}
Теперь и офисные файлы возвращаются нормально.