суббота, 23 марта 2013 г.

Файлы

А почему бы благородному дону не написать что-нибудь про файлы? Файлы - это очень нужная в хозяйстве вещь.


Откуда взять и куда положить файлы

Задумывались лы вы о том, откуда берутся файлы? В контексте веб-приложения возможны два основных варианта: уже готовый файл мы взяли "из тумбочки" (из файловой системы сервера или пользователя), или мы можем сами сгенерировать его в процессе работы приложения (например, отчет создать). Хранить файлы можно в файловой системе сервера или в таблице в BLOB поле. Ну и иногда отдавать файлы пользователю.
Например, мы решили хранить файлы в таблице. Например, в такой:
create table files(
id number,
file_name varchar2(255),
file_body blob,
updated date,
mime_type varchar2(100),
character_set varchar2(100));

В минимальном варианте нужны поля только для имени файла и его содержимого, а в самом минимальном варианте можно даже без имени файла обойтись. Но в апексе есть много всяких штучек, которые только и ждут момента, когда можно будет облегчить вам жизнь (о них ниже), поэтому сделаем дополнительные поля.

Теперь сделаем интерфейс для работы с файлами. Идем в Application Builder: Create Page -> Form -> Form on a Table with Report -> на закладке Report Page задаем значения по вкусу -> выбираем свежесозданную таблицу FILES в качестве источника данных для отчета -> далее выбираем разные варианты по вкусу из того, что предложит мастер создания страниц. Создаем страницу окончательно и запускаем ее.

И что мы видим в итоге? Мы видим готовый интерфейс для хранения файлов в БД. Да, вот так просто. У нас есть две страницы: первая - со списком файлов, вторая - с интерфейсом для загрузки. Нажимаем на первой странице Create и попадаем на вторую, где к нашим услугам уже готовое поле, позволяющее выбрать на вашем компьютере файл и загрузить его в вашу таблицу. Теперь выберите какой-нибудь файл и сохраните. После сохранения вы окажетесь на первой странице, где в отчете увидите одну строчку, соответствующую вашему файлу, и ссылку для загрузки.

Небольшой тюнинг

Теперь немного погрузимся в дебри апекса и оттюнингуем наш интерфейс до бесподобного состояния. Сначала пойдем на вторую страницу (которая с формой для загрузки) и найдем там элемент типа File Browse... - это то самое поле для выбора файла. У него в свойствах есть те самые "штучки" для облегчения вашей жизни (вашей жизни как разработчика, естественно - кофе варить и посуду мыть апекс пока не умеет), о которых я говорил выше. В разделе Settings есть поля MIME Type Column, Filename Column, Character Set Column, BLOB Last Updated Column. То есть если в вашей таблице есть поля для хранения этих атрибутов файла, вам достаточно указать их здесь, и всю остальную работу апекс возьмет на себя (надеюсь, что такое MIME Type и Character Set и зачем они нужны в интернете объяснять не нужно). Заполните эти поля (учтите, что они чувствительны к регистру), сохраните изменения и попробуйте загрузить еще один файл. На странице загрузки выберите файл, и, не заполняя остальные поля, нажмите кнопку Create. Вернувшись обратно на страницу с отчетом, вы увидите, что все поля заполнены.
Теперь запустите приложение еще раз и загрузите какую-нибудь картинку. Затем вернитесь в апекс, на странице с отчетом зайдите в Report Attributes отчета по таблице с файлами, зайдите в Column Attributes поля FILE_BODY и в разделе Blob Column Attributes измените свойство Format Mask на IMAGE. Теперь запустите отчет и узрите готовую фотогалерею!

Способ № 2

А теперь представим, что нашему пользователю лучше вообще не знать о том, что у нас есть таблица с файлами, и уж тем более не надо видеть список файлов. Нам надо просто дать ему возможность скачать файл из какого-нибудь места, просто по щелчку по кнопке или по ссылке.
Тут тоже все просто. Создаем пустую страницу. Вообще без всего. В разделе Processes создаем новый процесс типа PL/SQL, даем ему имя, в поле Point указываем On Load - Before Header, и пишем туда примерно такой код:

declare 
  v_file_name varchar2(255); 
  v_file_body blob; 
begin 
  dbms_lob.createtemporary(v_file_body, TRUE); 
  dbms_lob.open(v_file_body, dbms_lob.lob_readwrite); 

  select file_body, file_name 
    into v_file_body, v_file_name 
    from files f 
   where -- Здесь укажите условие, по которому вы будете однозначно 
   --  идентифицировать ваш файл. Будьте внимательны и осторожны,
   --  не словите NO_DATA_FOUND или TOO_MANY_ROWS
; 

  OWA_UTIL.mime_header ('text/html', FALSE, 'cp1251'); 
  htp.p('Content-Disposition:attachment; filename="' || v_file_name || '"'); 
  htp.p('Content-length: ' || dbms_lob.getlength(v_file_body)); 
  OWA_UTIL.http_header_close; 

  wpg_docload.download_file(v_file_body); 
  
  apex_application.g_unrecoverable_error:=true; 
exception 
  when others then 
    null; 
end;

Остается сделать две вещи. Первая - нужно указать условие, по которому вы будете искать файл. Например, вы можете сделать дополнительное поле с кодом в таблице FILES, дополнительный ITEM на странице загрузки и передавать код в этот ITEM c помощью ссылки, а в PL/SQL коде подставлять значение в секцию WHERE. Вторая - ссылка на эту страницу оттуда, где пользователь будет инициировать загрузку.
Этот код (с незначительными соответствующими модификациями) можно использовать для загрузки файла, хранящегося в файловой системе сервера (в этом случае файл нужно поместить в переменную  v_file_body, все остальное останется прежним), или для генерации файла с нуля (например, вы можете генерировать csv отчет или xml документ в формате Word или Excel).

Комментариев нет:

Отправить комментарий