Публикация ленты iCalendar с помощью Java

Microsoft Outlook и другие клиенты календаря имеют возможность подписаться на «Интернет-календари».

В случае Outlook он принимает URL-адрес (либо http:, либо webcal:). После правильной настройки «Интернет-календарь» появляется в клиенте Outlook и остается актуальным.

Я хотел бы знать, как самостоятельно опубликовать «Интернет-календарь». Я использую Java. Я уже создаю события "файлы .ics" с помощью библиотеки iCal4j. Я смутно предполагаю, что мне нужно создать сервлет, который отправляет поток событий ics.

Буду признателен за любой пример или справочную документацию, которая поможет мне начать.


person Frederic Fortier    schedule 17.12.2015    source источник
comment
Что такое события ICS/события ICS? Пожалуйста, определите и/или свяжите аббревиатуры, подобные этой. Вы имеете в виду файлы .ics, указанные в rfc 2445?   -  person Basil Bourque    schedule 17.12.2015
comment
Привет, Фредерик, я также ищу указатель для решения этой проблемы. Я мог бы реализовать Zapier, чтобы сделать это для меня, но я бы предпочел создать свой собственный сервлет для обработки канала. У вас уже есть решение? С уважением, Томас   -  person Thomas Dittmar    schedule 23.11.2016
comment
Я не смог этого сделать. Я не исследовал это намного дальше. В итоге я отправил эти приглашения календаря через SMTP, чего оказалось достаточно.   -  person Frederic Fortier    schedule 01.12.2016
comment
В чем именно ваша проблема? С iCal4j вы должны иметь возможность создавать файлы календаря, содержащие несколько событий, которые вы можете просто сохранить в файл или передать через HTTP из вашего серверного приложения. Вы даже можете записать его в статический файл ресурсов myCalendar.ics прямо на вашем веб-сервере. Если что-то в календаре изменится, просто перезапишите этот файл. Любой пользователь может добавить свой URL-адрес в свое приложение-календарь. Если вы не хотите, чтобы пользователи имели доступ для записи к календарю, с этим подходом не должно возникнуть никаких проблем. Если это поможет, пожалуйста, дайте мне знать, и я напишу ответ.   -  person kriegaex    schedule 22.07.2019
comment
У меня есть сервлет, который позволяет загружать mycalendar.ics, но когда я помещаю этот URL-адрес http в подписку на интернет-календарь Outlook, он не может импортировать файл без каких-либо ошибок. Однако, когда я открываю файл ics непосредственно из опции «Открыть календарь», он появляется. Я не уверен, в чем именно проблема.   -  person mod    schedule 22.07.2019


Ответы (1)


Я не знаю, как выглядит ваша реализация, но когда я попробовал какую-то фиктивную реализацию с Spring Boot, я смог заставить эту работу работать. Вот реализация, которую я использовал:

import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;

@Slf4j
@Controller
public class CalendarController {

  @GetMapping("/calendar.ics")
  @ResponseBody
  public byte[] getCalendars() throws IOException {
    ClassPathResource classPathResource = new ClassPathResource("Test.ics");
    InputStream inputStream = classPathResource.getInputStream();
    byte[] bytes = inputStream.readAllBytes();
    inputStream.close();
    return bytes;
  }

  @GetMapping("/downloadCalendar.ics")
  public ResponseEntity<Resource> downloadFile(HttpServletRequest request) {
    Resource resource = new ClassPathResource("Test.ics");
    String contentType = null;
    try {
      contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
    } catch (IOException ex) {
      log.info("Could not determine file type.");
    }

    if(contentType == null) {
      contentType = "application/octet-stream";
    }

    return ResponseEntity.ok()
        .contentType(MediaType.parseMediaType(contentType))
        .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
        .body(resource);
  }
}

Оба метода отлично работают в Outlook 2016 и более поздних версиях, если я пытаюсь добавить http://localhost:8080/calendar.ics или http://localhost:8080/downloadCalendar.ics. Test.ics Я возвращаюсь — это просто экспортированная встреча из моего календаря в формате ics. Также в качестве примечания приведены заголовки, которые отправляются с запросом из Outlook:

headers = [
    accept: "*/*", 
    user-agent: "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; Tablet PC 2.0; Microsoft Outlook 16.0.4861; ms-office; MSOffice 16)", 
    accept-encoding: "gzip, deflate", 
    host: "localhost:8080", 
    connection: "Keep-Alive"
]

Я также предположил бы, что могут возникнуть некоторые проблемы с аутентификацией, если используется https, и в этом случае Outlook может отправлять разные заголовки. В центре поддержки Microsoft есть отчет о проблеме: https://support.microsoft.com/en-us/help/4025591/you-can-t-add-an-internet-calendar-in-Outlook, но с неработающей ссылкой на страницу "новая современная аутентификация" :). Надеюсь это поможет.

person vl4d1m1r4    schedule 25.07.2019