2015
Contents
- Features
- Incoming photo automation
- Time-saving features for staff
- Integration
- Implementation Highlights
- Optimizing editor performance
- Flexible content delivery paths
Technology Stack
- PHP
- MySQL
- Oracle PL/SQL
- jQuery
- AWS S3
- Apache modules
I created an online photo submission and management app to be used with a higher-education enterprise campus card system. It replaced a process that consisted of manually downloading, identifying, and importing photos that cardholders submitted by email.
The app handles communication with cardholders regarding missing or rejected submissions, and performs two-way synchronization with the card system.
Ultimately, the app facilitates minimal input from office staff, allowing staff to efficiently process hundreds of submitted photos per day at peak times.
Features
Incoming photo automation
- Identification - In the weeks leading to the start of the academic year, the app checks the current list of incoming students for those who have not submitted a photo.
- Communication - The app sends reminder emails to each student who needs to submit a photo; each message is sent one week after the last communication to that person.
- Synchronization - When photos are approved and cropped by staff, the app uses Oracle Call Interface (OCI) to send edited photos to the Oracle database of the card system. Submitted photos are matched to the person in the card system by their ID number, which is available in the user object from the authentication system used to sign in to the app.
Time-saving features for staff
- Editing - The app integrates crop and rotation editing with Cropper.js.
- Workflow - The app provides multiple workflow options to conform to the editor's preference, such as a "save and next" button to move on to the next photo while the previous photo saves in the background.
- Communication - For photos that do not meet the requirements, the editor can select multiple common issues and enter custom text for less common issues. The app bundles these issues into a notification email and triggers the weekly reminder email until the student submits a new photo.
Integration
- Completeness - The app uses an Oracle query to detect new new photos added directly to the card system and adds them to the local database.
- External systems - The ID Photo API is consumed by other institutional systems and databases. They can query for photos updated in the last n days in order to transfer recent photos to their local databases.
- Flexibility and convenience - The photos are stored in AWS S3, but the current photo for each person is stored locally to provide flexible and performant hotlinking using Apache's mod_rewrite and mod_alias.
Implementation Highlights
Optimizing editor performance
When an image is uploaded, low- and medium-resolution images are stored alongside the original image. The low-resolution image is sent to the editor to minimize transfer time and optimize performance of the editor interface.
When the image is saved, only the rotation angle and crop dimensions are sent to the server. No image is sent back to the server. The app scales the dimensions up and applies them to the original image.
Flexible content delivery paths
A variety of external applications integrate ID photos, either embedding hotlinked images in web apps or downloading images to their own databases. Because these systems store ID numbers in a variety of formats, I configured Apache to accept multiple URL formats.
Photos are stored as nine-digit numbers, but the URLs can be padded by any number of zeros, and optionally preceded by a T
:
# All of these paths resolve to 001234567.jpg
/photo/001234567
/photo/1234567
/photo/000001234567
/photo/T01234567.jpg
Applications can also embed preferences in the URL. If they prefer to have a blank image instead of a 404
response for people without an image, they can add blank
to the path:
/photo/blank/001234567
Some external applications have their own flag for each person to show or hide the photo. They can add none
to the path to return a blank image in all cases, even if a photo does exist for that person:
/photo/none/001234567
These paths are supported by the following Apache configuration:
AliasMatch "^/photo/blank/?$" "/var/www/photos/blank_image.jpg"
<Macro PadPhoto ${digits} ${pad}>
AliasMatch "^/photo/((blank|none)/)?T?0*(\d{${digits}})(\.jpg)?$" "/var/www/photos/${pad}$3.jpg"
</Macro>
Use PadPhoto 9 ""
Use PadPhoto 8 0
Use PadPhoto 7 00
Use PadPhoto 6 000
Use PadPhoto 5 0000
Use PadPhoto 4 00000
Use PadPhoto 3 000000
Use PadPhoto 2 0000000
Use PadPhoto 1 00000000
<Directory /var/www/photos>
Options -Indexes +FollowSymLinks
Require all granted
ErrorDocument 404 "Photo not found"
# If /none/ option is used, show blank image always. This provides an
# easy URL pattern supporting those who do not want their picture shown
RewriteCond %{REQUEST_URI} /none/
RewriteRule (.*) /photo/blank/ [END]
# If /blank/ option is used, show a blank image instead of a 404 for bad ID numbers
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} /blank/
RewriteRule (.*) /photo/blank/ [END]
</Directory>