Check the docs before asking a question: https://abp.io/docs/latest Check the samples to see the basic tasks: https://abp.io/docs/latest/samples The exact solution to your question may have been answered before, and please first use the search on the homepage.
Provide us with the following info:
š§ Hint: If you are using the ABP Studio, you can see all the information about your solution from the configuration window, which opens when you right-click on the solution and click on the Solution Configuration button.
- Template: app
- Created ABP Studio Version: 1.0.2
- Current ABP Studio Version: 1.4.1
- Tiered: Yes
- Multi-Tenancy: Yes
- UI Framework: blazor-server
- Theme: leptonx
- Theme Style: system
- Theme Menu Placement: side
- Run Install Libs: Yes
- Database Provider: ef
- Database Management System: sqlserver
- Separate Tenant Schema: Yes
- Create Initial Migration: Yes
- Run Db Migrator: Yes
- Mobile Framework: maui
- Public Website: Yes
- Social Login: Yes
- Include Tests: Yes
- Kubernetes Configuration: No
- Distributed Event Bus: rabbitmq
- Use Local References: No
- Optional Modules:
- GDPR
- FileManagement
- TextTemplateManagement
- LanguageManagement
- AuditLogging
- Chat
- OpenIddictAdmin
- Selected Languages: English, English (United Kingdom), ē®ä½äøę, EspaƱol, Ų§ŁŲ¹Ų±ŲØŁŲ©, ą¤¹ą¤æą¤Øą„ą¤¦ą„, PortuguĆŖs (Brasil), FranƧais, Š ŃŃŃŠŗŠøŠ¹, Deutsch (Deuthschland), TürkƧe, Italiano, ÄeÅ”tina, Magyar, RomĆ¢nÄ (RomĆ¢nia), Svenska, Suomi, SlovenÄina, Ćslenska, ē¹é«äøę
- Default Language: English
- Create Command: abp new NewApp -t app --tiered --ui-framework blazor-server --mobile maui --database-provider ef --database-management-system sqlserver --theme leptonx --separate-tenant-schema --public-website --without-cms-kit --dont-run-bundling -chat -file-management
- Exception message and full stack trace:
- Steps to reproduce the issue:
I have a question regarding the default behavior of the ABP Suite templates, specifically related to file upload fields (as shown in the attached screenshot).

By default, when the user selects an image in the input field, the upload is triggered immediately on the frontend. The problem is that if the user cancels the operation like refreshing the page (F5) or closes/discards the form the uploaded file remains stored both in the file descriptor and in Blob Storage and there is no instruction on how to avoid it or cleanup procedure.
I would like to know what you recommend for handling this scenario, the ABP Architecture recomendation on how to handle this issue, as example below but not limited to them.
- Is there a way to adjust or extend the ABP Suite templates so that the upload only occurs during the Create action (i.e., only after the user clicks the SAVE button)?
- Is this issue mapped by ABP and there is a workaround solution until the fix to be implemented on a future release?
- Alternatively, is there a recommended approach to automatically clean up previously uploaded files when the user cancels the form?
I understand that it is possible to implement a fully custom upload flow but I preffer to keep as much as possible the standard ABP solution/architecture. Before going down that path for customization, I would like to know whether ABP Suite provides any recommended extension points or best practices to modify this default behavior.
Thank you in advance for your guidance.
2 Answer(s)
-
0
- In the ABP Suite-generated Blazor CRUD pages, the āFileā property uses a select file ā upload immediately UX. With BLOB Storage/File Management this means a
FileDescriptor+ blob content can be created before the main entity is saved. If the user closes the modal / refreshes, those uploaded blobs can remain orphaned unless you add a cleanup strategy. - There isnāt a built-in ABP Suite switch (template option) that changes this to āupload only on Saveā for generated pages (no verified source available for a Suite extension point that flips this behavior).
Recommended ABP-style approaches
A) āUpload on Saveā (recommended if you want zero orphan risk)
Implement the create/edit form so it does not call the server on file selection. Instead:
- On file selection, keep the file in memory (or stream) on the Blazor side and only show a preview.
- When the user clicks Save, call your Application Service
CreateAsync(...)and pass the file content asIRemoteStreamContent(or a byte[] if small), then inside the same application service method:- Create the entity
- Save the blob
- Store the blob/file id on the entity
- Commit once (same unit of work)
This matches ABPās general ādo it in the application service in a single use-caseā style and avoids a ātemporary uploadā concept entirely.
B) Keep immediate upload, but add an automatic cleanup (recommended if you want to keep Suite UX)
If you keep the default immediate upload, use a ātemporary uploadā + scheduled cleanup pattern:
- When the file is uploaded, mark it as temporary (e.g., store a flag/metadata, or put it under a ātemp/ā naming convention, or store it in a dedicated container).
- When the user clicks Save and the entity is created, āfinalizeā the file:
- clear the temporary flag (or move/rename)
- associate it with the created entity
- Run a background job (periodic worker) that deletes temporary files older than X minutes/hours (and their descriptors).
ABPās Blob Storing API supports deleting blobs, so the cleanup job can safely remove old temporary items.
C) Compensating cleanup on Cancel (best-effort only)
In the modalās Cancel/Close handler (and on dispose/navigation), call an endpoint to delete the already-uploaded file descriptor/blob if it hasnāt been finalized. This reduces leftovers but wonāt cover hard refresh/tab close/network lossāso you still typically want (B) as the safety net.
Minimal cleanup code idea (server side)
Use ABP Blob Storingās container API to remove orphaned blobs when needed (e.g., in a background worker or explicit cancel endpoint):
public class MyFileCleanupService : ITransientDependency { private readonly IBlobContainer<MyFileContainer> _container; public MyFileCleanupService(IBlobContainer<MyFileContainer> container) { _container = container; } public Task DeleteAsync(string blobName) { return _container.DeleteAsync(blobName); } }Youād combine this with whatever ātemporaryā tracking you use (DB table/flag, naming convention, etc.) to find candidates to delete.
References (verified)
- https://docs.abp.io/en/abp/latest/Blob-Storing
- https://abp.io/community/articles/d01cbe12
- https://abp.io/community/articles/sr7t3w4p
This response was generated by AI. If it didnāt solve your problem, feel free to post a new answer ā our support team will jump in to help you soon.
- In the ABP Suite-generated Blazor CRUD pages, the āFileā property uses a select file ā upload immediately UX. With BLOB Storage/File Management this means a
-
0
Hi ABP Folks,
I“d like to get an architect guy guidance instead of bot answer to be as close as possible of the ABP solution evolution.
