I've written some PHP code to generate an ICS file for a user to download and add to their own calendar. It works fine on desktop Safari (macOS 12.6), and it also works fine if I airdrop the downloaded ICS file to my iPhone. However, if I try to download the ICS file directly on mobile safari (iOS 16.1.2) I get the message "Safari cannot download this file".
Do I need to sign the file somehow? or is the PHP 'readfile' command not allowed on iOS?
Thanks!
`<?php
// Get the event details from the form data
$result_sched = json_decode($_POST['result_sched'], true);
$returnedCountSched = json_decode($_POST['returnedCountSched'], true);
// Open the ICS file for writing
$icsFile = fopen("events.ics", "w");
// Write the ICS file header
fwrite($icsFile, "BEGIN:VCALENDAR\n");
fwrite($icsFile, "PRODID:-//Your Company//Product//Language\n");
fwrite($icsFile, "VERSION:2.0\n");
fwrite($icsFile, "METHOD:PUBLISH\n");
// Iterate through the loop and write each event to the ICS file
for ($j = 0; $j < $returnedCountSched; $j++) {
// Get the date and time strings from the result_sched array
$date_string = $result_sched['response']['data'][$j]['fieldData']['service_date'];
$start_time_string = $result_sched['response']['data'][$j]['fieldData']['service_start_time'];
$end_time_string = $result_sched['response']['data'][$j]['fieldData']['service_end_time'];
// set time zone to los angeles
date_default_timezone_set('America/Los_Angeles');
// Format the date and time strings
$date = date("Ymd", strtotime($date_string));
$start_time = date("His", strtotime($start_time_string));
$end_time = date("His", strtotime($end_time_string));
// Combine the date and time strings and convert to a timestamp
$start_timestamp = strtotime("$date $start_time");
$end_timestamp = strtotime("$date $end_time");
// Format the timestamp as an ICS-formatted DTSTART string
$dtstart = gmdate("Ymd\THis\Z", $start_timestamp);
$dtend = gmdate("Ymd\THis\Z", $end_timestamp);
$location = $result_sched['response']['data'][$j]['fieldData']['service_venue_name'];
$summary = $result_sched['response']['data'][$j]['fieldData']['service_title'];
$description = $result_sched['response']['data'][$j]['fieldData']['rehearsal_order_summary'];
// Write the event to the ICS file
fwrite($icsFile, "BEGIN:VEVENT\n");
fwrite($icsFile, "DTSTART:$dtstart\n");
fwrite($icsFile, "DTEND:$dtend\n");
fwrite($icsFile, "LOCATION:$location\n");
fwrite($icsFile, "SUMMARY:$summary\n");
fwrite($icsFile, "DESCRIPTION:$description\n");
fwrite($icsFile, "END:VEVENT\n");
}
fwrite($icsFile, "END:VCALENDAR\n");
fclose($icsFile);
// Output the ICS file as a download
header('Content-Description: File Transfer');
header('Content-Type: text/calendar; charset=utf-8');
//header("Content-Type: application/force-download");
header('Content-Disposition: attachment; filename=events.ics');
// header('Content-Transfer-Encoding: binary');
// header('Expires: 0');
// header('Cache-Control: must-revalidate');
// header('Pragma: public');
// Output the ICS file
readfile('events.ics');
?>`
I've also tried this in Chrome on the desktop and I get 0 byte download files, whereas I get the expected ICS file when download on desktop Safari. I must be doing something wrong!
I feel like it has something to do with how I'm setting the headers, but I'm at a loss.