mirror of
https://github.com/danieleteti/delphimvcframework.git
synced 2024-11-15 15:55:54 +01:00
NEW SAMPLE: Render Binary Contents
This commit is contained in:
parent
6d22cf6c6e
commit
8ac772f871
138
samples/render_binary_contents/ControllerU.pas
Normal file
138
samples/render_binary_contents/ControllerU.pas
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
unit ControllerU;
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
MVCFramework, MVCFramework.Commons, MVCFramework.Serializer.Commons, System.Generics.Collections,
|
||||||
|
System.Classes;
|
||||||
|
|
||||||
|
type
|
||||||
|
[MVCPath('/api')]
|
||||||
|
TMyController = class(TMVCController)
|
||||||
|
public
|
||||||
|
[MVCPath('/files/($FileName)')]
|
||||||
|
[MVCHTTPMethod([httpGET])]
|
||||||
|
function GetFileByName(const FileName: String): TStream;
|
||||||
|
|
||||||
|
[MVCPath('/files2/($FileName)')]
|
||||||
|
[MVCHTTPMethod([httpGET])]
|
||||||
|
procedure GetStreamByFileName(const FileName: String);
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
uses
|
||||||
|
System.SysUtils,
|
||||||
|
System.IOUtils,
|
||||||
|
MVCFramework.Logger,
|
||||||
|
System.StrUtils;
|
||||||
|
|
||||||
|
{ TMyController }
|
||||||
|
|
||||||
|
{
|
||||||
|
This action show how to return binary contents using a functional action (the action is a function)
|
||||||
|
}
|
||||||
|
function TMyController.GetFileByName(const FileName: String): TStream;
|
||||||
|
var
|
||||||
|
lPath: String;
|
||||||
|
lExt: String;
|
||||||
|
begin
|
||||||
|
lPath := TPath.Combine(TPath.Combine(TDirectory.GetParent(AppPath), 'files_repository'), FileName);
|
||||||
|
lPath := TPath.GetFullPath(lPath);
|
||||||
|
if not lPath.StartsWith(AppPath) then // directory traversal check
|
||||||
|
begin
|
||||||
|
raise EMVCException.Create(HTTP_STATUS.BadRequest, 'Invalid path');
|
||||||
|
end;
|
||||||
|
|
||||||
|
LogD(Context.QualifiedClassName + ': ' + lPath);
|
||||||
|
|
||||||
|
if not TFile.Exists(lPath) then
|
||||||
|
begin
|
||||||
|
raise EMVCException.Create(HTTP_STATUS.NotFound, 'File not found');
|
||||||
|
end;
|
||||||
|
|
||||||
|
lExt := TPath.GetExtension(lPath).ToLower;
|
||||||
|
|
||||||
|
if lExt = '.jpg' then
|
||||||
|
begin
|
||||||
|
Context.Response.ContentType := TMVCMediaType.IMAGE_JPEG;
|
||||||
|
end
|
||||||
|
else if lExt = '.txt' then
|
||||||
|
begin
|
||||||
|
Context.Response.ContentType := TMVCMediaType.TEXT_PLAIN;
|
||||||
|
end
|
||||||
|
else if lExt = '.pdf' then
|
||||||
|
begin
|
||||||
|
Context.Response.ContentType := TMVCMediaType.APPLICATION_PDF;
|
||||||
|
end
|
||||||
|
else if lExt = '.png' then
|
||||||
|
begin
|
||||||
|
Context.Response.ContentType := TMVCMediaType.IMAGE_PNG;
|
||||||
|
end
|
||||||
|
else if lExt = '.html' then
|
||||||
|
begin
|
||||||
|
Context.Response.ContentType := TMVCMediaType.TEXT_HTML;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
Context.Response.ContentType := TMVCMediaType.APPLICATION_OCTET_STREAM;
|
||||||
|
end;
|
||||||
|
StatusCode := HTTP_STATUS.OK;
|
||||||
|
Result := TFileStream.Create(lPath, fmOpenRead, fmShareDenyNone)
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
This action show how to return binary contents using a classic action (the action is a procedure)
|
||||||
|
}
|
||||||
|
procedure TMyController.GetStreamByFileName(const FileName: String);
|
||||||
|
var
|
||||||
|
lPath: String;
|
||||||
|
lExt: String;
|
||||||
|
begin
|
||||||
|
lPath := TPath.Combine(TPath.Combine(TDirectory.GetParent(AppPath), 'files_repository'), FileName);
|
||||||
|
lPath := TPath.GetFullPath(lPath);
|
||||||
|
if not lPath.StartsWith(AppPath) then // directory traversal check
|
||||||
|
begin
|
||||||
|
raise EMVCException.Create(HTTP_STATUS.BadRequest, 'Invalid path');
|
||||||
|
end;
|
||||||
|
|
||||||
|
LogD(Context.QualifiedClassName + ': ' + lPath);
|
||||||
|
|
||||||
|
if not TFile.Exists(lPath) then
|
||||||
|
begin
|
||||||
|
raise EMVCException.Create(HTTP_STATUS.NotFound, 'File not found');
|
||||||
|
end;
|
||||||
|
|
||||||
|
lExt := TPath.GetExtension(lPath).ToLower;
|
||||||
|
|
||||||
|
if lExt = '.jpg' then
|
||||||
|
begin
|
||||||
|
Context.Response.ContentType := TMVCMediaType.IMAGE_JPEG;
|
||||||
|
end
|
||||||
|
else if lExt = '.txt' then
|
||||||
|
begin
|
||||||
|
Context.Response.ContentType := TMVCMediaType.TEXT_PLAIN;
|
||||||
|
end
|
||||||
|
else if lExt = '.pdf' then
|
||||||
|
begin
|
||||||
|
Context.Response.ContentType := TMVCMediaType.APPLICATION_PDF;
|
||||||
|
end
|
||||||
|
else if lExt = '.png' then
|
||||||
|
begin
|
||||||
|
Context.Response.ContentType := TMVCMediaType.IMAGE_PNG;
|
||||||
|
end
|
||||||
|
else if lExt = '.html' then
|
||||||
|
begin
|
||||||
|
Context.Response.ContentType := TMVCMediaType.TEXT_HTML;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
Context.Response.ContentType := TMVCMediaType.APPLICATION_OCTET_STREAM;
|
||||||
|
end;
|
||||||
|
StatusCode := HTTP_STATUS.OK;
|
||||||
|
SendFile(lPath);
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
7
samples/render_binary_contents/WebModuleU.dfm
Normal file
7
samples/render_binary_contents/WebModuleU.dfm
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
object MyWebModule: TMyWebModule
|
||||||
|
OnCreate = WebModuleCreate
|
||||||
|
OnDestroy = WebModuleDestroy
|
||||||
|
Actions = <>
|
||||||
|
Height = 230
|
||||||
|
Width = 415
|
||||||
|
end
|
82
samples/render_binary_contents/WebModuleU.pas
Normal file
82
samples/render_binary_contents/WebModuleU.pas
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
unit WebModuleU;
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
System.SysUtils,
|
||||||
|
System.Classes,
|
||||||
|
Web.HTTPApp,
|
||||||
|
MVCFramework;
|
||||||
|
|
||||||
|
type
|
||||||
|
TMyWebModule = class(TWebModule)
|
||||||
|
procedure WebModuleCreate(Sender: TObject);
|
||||||
|
procedure WebModuleDestroy(Sender: TObject);
|
||||||
|
private
|
||||||
|
fMVC: TMVCEngine;
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
WebModuleClass: TComponentClass = TMyWebModule;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
{$R *.dfm}
|
||||||
|
|
||||||
|
uses
|
||||||
|
System.IOUtils,
|
||||||
|
MVCFramework.Commons,
|
||||||
|
MVCFramework.Middleware.ActiveRecord,
|
||||||
|
MVCFramework.Middleware.StaticFiles,
|
||||||
|
MVCFramework.Middleware.Analytics,
|
||||||
|
MVCFramework.Middleware.Trace,
|
||||||
|
MVCFramework.Middleware.CORS,
|
||||||
|
MVCFramework.Middleware.ETag,
|
||||||
|
MVCFramework.Middleware.Compression, ControllerU;
|
||||||
|
|
||||||
|
procedure TMyWebModule.WebModuleCreate(Sender: TObject);
|
||||||
|
begin
|
||||||
|
FMVC := TMVCEngine.Create(Self,
|
||||||
|
procedure(Config: TMVCConfig)
|
||||||
|
begin
|
||||||
|
// session timeout (0 means session cookie)
|
||||||
|
Config[TMVCConfigKey.SessionTimeout] := dotEnv.Env('dmvc.session_timeout', '0');
|
||||||
|
//default content-type
|
||||||
|
Config[TMVCConfigKey.DefaultContentType] := dotEnv.Env('dmvc.default.content_type', TMVCConstants.DEFAULT_CONTENT_TYPE);
|
||||||
|
//default content charset
|
||||||
|
Config[TMVCConfigKey.DefaultContentCharset] := dotEnv.Env('dmvc.default.content_charset', TMVCConstants.DEFAULT_CONTENT_CHARSET);
|
||||||
|
//unhandled actions are permitted?
|
||||||
|
Config[TMVCConfigKey.AllowUnhandledAction] := dotEnv.Env('dmvc.allow_unhandled_actions', 'false');
|
||||||
|
//enables or not system controllers loading (available only from localhost requests)
|
||||||
|
Config[TMVCConfigKey.LoadSystemControllers] := dotEnv.Env('dmvc.load_system_controllers', 'true');
|
||||||
|
//default view file extension
|
||||||
|
Config[TMVCConfigKey.DefaultViewFileExtension] := dotEnv.Env('dmvc.default.view_file_extension', 'html');
|
||||||
|
//view path
|
||||||
|
Config[TMVCConfigKey.ViewPath] := dotEnv.Env('dmvc.view_path', 'templates');
|
||||||
|
//use cache for server side views (use "false" in debug and "true" in production for faster performances
|
||||||
|
Config[TMVCConfigKey.ViewCache] := dotEnv.Env('dmvc.view_cache', 'false');
|
||||||
|
//Max Record Count for automatic Entities CRUD
|
||||||
|
Config[TMVCConfigKey.MaxEntitiesRecordCount] := dotEnv.Env('dmvc.max_entities_record_count', IntToStr(TMVCConstants.MAX_RECORD_COUNT));
|
||||||
|
//Enable Server Signature in response
|
||||||
|
Config[TMVCConfigKey.ExposeServerSignature] := dotEnv.Env('dmvc.expose_server_signature', 'false');
|
||||||
|
//Enable X-Powered-By Header in response
|
||||||
|
Config[TMVCConfigKey.ExposeXPoweredBy] := dotEnv.Env('dmvc.expose_x_powered_by', 'true');
|
||||||
|
// Max request size in bytes
|
||||||
|
Config[TMVCConfigKey.MaxRequestSize] := dotEnv.Env('dmvc.max_request_size', IntToStr(TMVCConstants.DEFAULT_MAX_REQUEST_SIZE));
|
||||||
|
end);
|
||||||
|
|
||||||
|
// Controllers
|
||||||
|
FMVC.AddController(TMyController);
|
||||||
|
// Controllers - END
|
||||||
|
|
||||||
|
// Middleware
|
||||||
|
// Middleware - END
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMyWebModule.WebModuleDestroy(Sender: TObject);
|
||||||
|
begin
|
||||||
|
FMVC.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
Before Width: | Height: | Size: 199 KiB After Width: | Height: | Size: 199 KiB |
Before Width: | Height: | Size: 180 KiB After Width: | Height: | Size: 180 KiB |
Before Width: | Height: | Size: 138 KiB After Width: | Height: | Size: 138 KiB |
83
samples/render_binary_contents/render_binary_contents.dpr
Normal file
83
samples/render_binary_contents/render_binary_contents.dpr
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
program render_binary_contents;
|
||||||
|
|
||||||
|
{$APPTYPE CONSOLE}
|
||||||
|
|
||||||
|
uses
|
||||||
|
System.SysUtils,
|
||||||
|
Web.ReqMulti,
|
||||||
|
Web.WebReq,
|
||||||
|
Web.WebBroker,
|
||||||
|
IdContext,
|
||||||
|
IdHTTPWebBrokerBridge,
|
||||||
|
MVCFramework,
|
||||||
|
MVCFramework.Logger,
|
||||||
|
MVCFramework.DotEnv,
|
||||||
|
MVCFramework.Commons,
|
||||||
|
MVCFramework.Serializer.Commons,
|
||||||
|
MVCFramework.Signal,
|
||||||
|
ControllerU in 'ControllerU.pas',
|
||||||
|
WebModuleU in 'WebModuleU.pas' {MyWebModule: TWebModule};
|
||||||
|
|
||||||
|
{$R *.res}
|
||||||
|
|
||||||
|
procedure RunServer(APort: Integer);
|
||||||
|
var
|
||||||
|
LServer: TIdHTTPWebBrokerBridge;
|
||||||
|
begin
|
||||||
|
LServer := TIdHTTPWebBrokerBridge.Create(nil);
|
||||||
|
try
|
||||||
|
LServer.OnParseAuthentication := TMVCParseAuthentication.OnParseAuthentication;
|
||||||
|
LServer.DefaultPort := APort;
|
||||||
|
LServer.KeepAlive := dotEnv.Env('dmvc.indy.keep_alive', True);
|
||||||
|
LServer.MaxConnections := dotEnv.Env('dmvc.webbroker.max_connections', 0);
|
||||||
|
LServer.ListenQueue := dotEnv.Env('dmvc.indy.listen_queue', 500);
|
||||||
|
LServer.Active := True;
|
||||||
|
LogI('Listening on port ' + APort.ToString);
|
||||||
|
LogI('Application started. Press Ctrl+C to shut down.');
|
||||||
|
WaitForTerminationSignal;
|
||||||
|
EnterInShutdownState;
|
||||||
|
LServer.Active := False;
|
||||||
|
finally
|
||||||
|
LServer.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
{ Enable ReportMemoryLeaksOnShutdown during debug }
|
||||||
|
// ReportMemoryLeaksOnShutdown := True;
|
||||||
|
IsMultiThread := True;
|
||||||
|
|
||||||
|
// DMVCFramework Specific Configurations
|
||||||
|
// When MVCSerializeNulls = True empty nullables and nil are serialized as json null.
|
||||||
|
// When MVCSerializeNulls = False empty nullables and nil are not serialized at all.
|
||||||
|
MVCSerializeNulls := True;
|
||||||
|
|
||||||
|
// MVCNameCaseDefault defines the name case of property names generated by the serializers.
|
||||||
|
// Possibile values are: ncAsIs, ncUpperCase, ncLowerCase (default), ncCamelCase, ncPascalCase, ncSnakeCase
|
||||||
|
MVCNameCaseDefault := TMVCNameCase.ncLowerCase;
|
||||||
|
|
||||||
|
// UseConsoleLogger defines if logs must be emitted to also the console (if available).
|
||||||
|
UseConsoleLogger := True;
|
||||||
|
|
||||||
|
LogI('** DMVCFramework Server ** build ' + DMVCFRAMEWORK_VERSION);
|
||||||
|
|
||||||
|
try
|
||||||
|
if WebRequestHandler <> nil then
|
||||||
|
WebRequestHandler.WebModuleClass := WebModuleClass;
|
||||||
|
|
||||||
|
WebRequestHandlerProc.MaxConnections := dotEnv.Env('dmvc.handler.max_connections', 1024);
|
||||||
|
|
||||||
|
{$IF CompilerVersion >= 34} //SYDNEY+
|
||||||
|
if dotEnv.Env('dmvc.profiler.enabled', false) then
|
||||||
|
begin
|
||||||
|
Profiler.ProfileLogger := Log;
|
||||||
|
Profiler.WarningThreshold := dotEnv.Env('dmvc.profiler.warning_threshold', 2000);
|
||||||
|
end;
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
RunServer(dotEnv.Env('dmvc.server.port', 8080));
|
||||||
|
except
|
||||||
|
on E: Exception do
|
||||||
|
LogF(E.ClassName + ': ' + E.Message);
|
||||||
|
end;
|
||||||
|
end.
|
1043
samples/render_binary_contents/render_binary_contents.dproj
Normal file
1043
samples/render_binary_contents/render_binary_contents.dproj
Normal file
File diff suppressed because it is too large
Load Diff
@ -43,7 +43,9 @@ uses
|
|||||||
System.Generics.Collections,
|
System.Generics.Collections,
|
||||||
MVCFramework.DuckTyping,
|
MVCFramework.DuckTyping,
|
||||||
JsonDataObjects,
|
JsonDataObjects,
|
||||||
MVCFramework.DotEnv, MVCFramework.Container, sqids;
|
MVCFramework.DotEnv,
|
||||||
|
MVCFramework.Container,
|
||||||
|
sqids;
|
||||||
|
|
||||||
{$I dmvcframeworkbuildconsts.inc}
|
{$I dmvcframeworkbuildconsts.inc}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user