Working with Files
In this example, we will show how to create an application for managing images. After reading this article, you will learn how to upload, save, display, and manage images.
Main Steps
Importing Libraries
We import the modules attachMedia
, refresh
from @app/ui
, and Heap
from @app/heap
.
import {attachMedia, refresh} from '@app/ui'
import {Heap} from '@app/heap'
attachMedia
allows you to attach media files.refresh
updates the screen.Heap
from@app/heap
is used for database operations.
Creating a Table
const ImagesTable = Heap.Table('images', {
filename: Heap.String(),
image: Heap.ImageFile(),
sessionId: Heap.String(),
})
ImagesTable
defines the structure of the table with fields:filename
, which displays the name of the fileimage
- the image filesessionId
- the session identifier where future uploaded files will be stored.
Main Screen
We define the route /
, which displays the main screen with the title "File manager", and it will show future files in a table format.
app.screen('/', async (ctx, req) => {
const records = await ImagesTable.findAll(ctx, {
where: { sessionId: ctx.session.id }
})
return (
<screen title="File manager">
<text class="section">Select image file to upload</text>
{records.map(record =>
<list-item
icon={{ url: record.image.getThumbnailUrl(80) }}
content={{ title: record.filename, subTitle: record.createdAt.toLocaleDateString() }}
onClick={cardRoute({id: record.id}).navigate()}
/>
)}
ctx
andreq
— context and request used for data processing.ImagesTable.
findAll retrieves all image records for the current session.screen
creates a screen with the title "File manager".text
outputs the text "Select image file to upload".records.map
iterates through all records and creates list items list-item with an image icon, title, and creation date.
<button class={['section', 'primary']}
onClick={attachMedia({
mediaType: 'photo',
submitUrl: uploadRoute.url()
})}
>Upload</button>
</screen>
)
})
- We add a button "Upload", which calls the
attachMedia
function to upload an image. When the button is clicked, a dialog opens to select a photo, and then the upload routeuploadRoute
is called.
Upload Route
At this stage, we define the route /upload
, which handles image uploads.
const uploadRoute = app.apiCall('/upload', async(ctx, req) => {
await ImagesTable.create(ctx, {
filename: req.body.file.name,
image: req.body.file.hash,
sessionId: ctx.session.id,
})
return refresh()
})
uploadRoute
is an API request for uploading images.ImagesTable.create
creates a new record in the table with data about the uploaded file.
After successfully uploading and saving the image, the refresh
function is called to update the current screen so that the new file appears.
Image Card
To display a single image, we need to define the route /card/:id
.
const cardRoute = app.screen('/card/:id', async(ctx, req) => {
const record = await ImagesTable.getById(ctx, req.params.id)
return <screen title={record.filename}>
<image src={record.image.getThumbnailSrc(800)} />
<button class={['section', 'secondary']} onClick={ctx.router.navigate('/')}>Back</button>
</screen>
})
Here we define a screen for the route /card/:id
. Then, using ImagesTable.getById(ctx, req.params.id)
, we retrieve the record from the ImagesTable by the identifier passed in the URL and display a screen with a title corresponding to the image file name (screen title={record.filename}
). Using image src={record.image.getThumbnailSrc(800)}
, we insert the image with a width of 800 pixels. We also add a "Back" button that returns the user to the main screen (button c ctx.router.navigate('/')
).
Conclusion
This code demonstrates creating a table for storing images, defining routes for displaying and uploading images, as well as creating dynamic interfaces for managing these images.