Обработка загрузки бинарных файлов в DelphiMVCFramework с использованием MULTIPART_FORM_DATA
Введение
При разработке веб-приложений на Delphi с использованием DelphiMVCFramework часто возникает необходимость обработки загрузки файлов. В этой статье мы рассмотрим, как правильно настроить обработку бинарных файлов с атрибутом [MVCConsumes(TMVCMediaType.MULTIPART_FORM_DATA)] в Delphi 11.3.
Проблема и ее решение
Как отмечает пользователь в исходном вопросе, при добавлении атрибута [MVCConsumes(TMVCMediaType.MULTIPART_FORM_DATA)] к методу контроллера, эндпоинт может "исчезать" из маршрутизации. Рассмотрим правильный способ настройки такого обработчика.
Базовый код контроллера
type
[MVCPath('/api')]
TMyController = class(TMVCController)
public
[MVCPath('/upload')]
[MVCHTTPMethod([httpPOST])]
[MVCConsumes(TMVCMediaType.MULTIPART_FORM_DATA)]
function Upload: IMVCResponse;
end;
Реализация метода Upload
function TMyController.Upload: IMVCResponse;
var
LFile: TWebRequestFile;
LFileStream: TFileStream;
LUploadDir: string;
begin
// Проверяем, есть ли загруженные файлы
if Context.Request.Files.Count = 0 then
Exit(HTTPResponse(HTTP_STATUS.BadRequest, 'No files uploaded'));
// Получаем первый файл (можно обработать все файлы в цикле)
LFile := Context.Request.Files[0];
// Создаем директорию для загрузки, если ее нет
LUploadDir := IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0))) + 'uploads';
ForceDirectories(LUploadDir);
// Сохраняем файл на диск
LFileStream := TFileStream.Create(
IncludeTrailingPathDelimiter(LUploadDir) + LFile.FileName,
fmCreate
);
try
LFileStream.CopyFrom(LFile.Stream, 0);
finally
LFileStream.Free;
end;
// Возвращаем успешный ответ
Result := HTTPResponse(HTTP_STATUS.OK, 'File uploaded successfully');
end;
Ключевые моменты для корректной работы
Обязательное подключение модуля Web.ReqMulti: Хотя в некоторых случаях он может подключаться автоматически, лучше явно добавить его в uses-секцию.
Правильная настройка Postman:
Установите метод POST
Выберите тип form-data
Для файла укажите ключ (не оставляйте поле "key" пустым)
Выберите тип "File" и укажите файл для загрузки
Альтернативное решение: Если проблема с [MVCConsumes] сохраняется, можно попробовать обрабатывать загрузку вручную:
function TMyController.Upload: IMVCResponse;
var
LContentType: string;
begin
LContentType := Context.Request.ContentType;
if not LContentType.Contains('multipart/form-data') then
Exit(HTTPResponse(HTTP_STATUS.BadRequest, 'Invalid content type'));
// Далее обработка как в предыдущем примере
// ...
end;
Обработка нескольких файлов
Для обработки нескольких файлов можно использовать следующий подход:
function TMyController.UploadMultiple: IMVCResponse;
var
I: Integer;
LFile: TWebRequestFile;
LUploadDir: string;
LSuccessCount: Integer;
begin
LSuccessCount := 0;
LUploadDir := IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0))) + 'uploads';
ForceDirectories(LUploadDir);
for I := 0 to Context.Request.Files.Count - 1 do
begin
LFile := Context.Request.Files[I];
try
LFile.Stream.Position := 0;
LFile.Stream.SaveToFile(IncludeTrailingPathDelimiter(LUploadDir) + LFile.FileName);
Inc(LSuccessCount);
except
on E: Exception do
Log.Error('Error saving file ' + LFile.FileName + ': ' + E.Message);
end;
end;
Result := HTTPResponse(HTTP_STATUS.OK,
Format('%d of %d files uploaded successfully',
[LSuccessCount, Context.Request.Files.Count]));
end;
Проверка размера файла
Важно ограничивать размер загружаемых файлов:
function TMyController.Upload: IMVCResponse;
const
MAX_FILE_SIZE = 10 * 1024 * 1024; // 10 MB
var
LFile: TWebRequestFile;
begin
if Context.Request.Files.Count = 0 then
Exit(HTTPResponse(HTTP_STATUS.BadRequest, 'No files uploaded'));
LFile := Context.Request.Files[0];
if LFile.Size > MAX_FILE_SIZE then
Exit(HTTPResponse(HTTP_STATUS.RequestEntityTooLarge, 'File size exceeds limit'));
// ... остальная обработка
end;
Настройка маршрутизации
Если эндпоинт "исчезает", проверьте:
Правильность регистрации контроллера в DMVCFramework
Наличие всех необходимых атрибутов
Корректность работы Web.ReqMulti
Пример регистрации контроллера:
procedure TWebModule1.WebModuleCreate(Sender: TObject);
begin
FMVC := TMVCEngine.Create(Self);
FMVC.AddController(TMyController);
// Другие настройки...
end;
Заключение
Обработка загрузки файлов в DelphiMVCFramework требует внимания к нескольким ключевым аспектам: правильной настройке атрибутов контроллера, обработке multipart/form-data запросов и корректной работе с модулем Web.ReqMulti. Представленные в статье решения помогут вам реализовать надежный механизм загрузки файлов в ваших приложениях.
Если проблема с "исчезновением" эндпоинта сохраняется, рекомендуется проверить версию DelphiMVCFramework на наличие известных проблем или рассмотреть альтернативные подходы к обработке файлов, описанные в статье.
Статья описывает методы обработки загрузки бинарных файлов в DelphiMVCFramework с использованием MULTIPART_FORM_DATA в Delphi 11.3.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.