QR-код из backend можно скачать при нажатии кнопки на Android, ПК и ноутбуке, а на iOS это не работает. Как решить эту проблему?

На iOS при попытке сохранить QR-код появляется ошибка "the operation is insecure", в то время как на Android PDF-файл скачивается без проблем. Как можно решить данную проблему?

```javascript
"use client";

import { UserInfoBlock } from "@/src/entites/UserInfoBlock";
import api from "@/src/shared/api/api";
import { defaultToastStyles } from "@/src/shared/model/defaultStyles/defaultStyles";
import { copyTextToClipboard } from "@/src/shared/model/functions/copyToClipboard";
import { useUserStore } from "@/src/shared/store/store";
import { Button, IButtonSize } from "@/src/shared/ui/Button/Button";
import { useQuery } from "@tanstack/react-query";
import html2canvas from "html2canvas";
import { jsPDF } from "jspdf";
import Image from "next/image";
import { useEffect, useRef, useState } from "react";
import toast from "react-hot-toast";
import { QrImageSave } from "../QrImageSave/QrImageSave";
import styles from "./Qr.module.scss";

export const Qr = () => {
  const printRef = useRef(null);

  const [qrSrc, setQrSrc] = useState<string | null>(null);

  const userId = useUserStore((state) => state.data.id);
  const userName = useUserStore((state) => state.data.name);
  const userAvatar = useUserStore((state) => state.data.avatar);
  const userGoal = useUserStore((state) => state.data.goal);

  const qrLink = `https://saluttipe.site/qr_code/user/${userId}`;

  const { data } = useQuery({
    queryKey: ["qr"],
    queryFn: async () => {
      const response = await api.get("profile/me/qr-code/", {
        responseType: "blob",
      });
      return response.data;
    },
  });

  useEffect(() => {
    if (data) {
      const qrUrl = URL.createObjectURL(data);
      setQrSrc(qrUrl);
    }
  }, [data]);
}
```
  • 28 февраля 2025 г. 10:34
Ответы на вопрос 1
Проблема с загрузкой QR-кода на iOS может быть связана с различиями в обработке безопасных операций для получения бинарного контента и его работы с объектами URL. Ошибка `"the operation is insecure"` указывает на то, что iOS ограничивает загрузку файлов, которые были созданы через интерфейсы, не относящиеся к безопасным контекстам (например, использующими сам процесс `fetch` или загрузку из других источников).

Вот несколько рекомендаций по решению данной проблемы:

### 1. Используйте `<a>` тег для загрузки

Одним из распространенных способов решения данной проблемы является использование элемента `<a>`, чтобы инициировать загрузку. Убедитесь, что при этом элемент имеет атрибут `download`. Вот пример изменения вашего кода:

```javascript
const handleDownload = () => {
  if (!qrSrc) return;

  // Создаем ссылку, указывая ее URL и заголовок для загрузки
  const link = document.createElement('a');
  link.href = qrSrc; // URL, созданный выше
  link.download = `qr_code_${userId}.png`; // Имя файла для загрузки

  // Добавляем ссылку на документ и инициируем клик
  document.body.appendChild(link);
  link.click();

  // Удаляем ссылку после завершения загрузки
  document.body.removeChild(link);

  // Освобождаем объект URL
  URL.revokeObjectURL(qrSrc);
};
```

### 2. Использование `fetch` для обработки бинарных данных

Если ваш сервер возвращает QR-код в виде бинарных данных, вы можете использовать функцию `fetch` для получения данных и их обработки. Примерный код для этого:

```javascript
const fetchQrCode = async () => {
  const response = await fetch("https://api.example.com/profile/me/qr-code/");
  const blob = await response.blob(); // Получаем blob из ответа
  const qrUrl = URL.createObjectURL(blob); // Создаем объект URL для blob
  setQrSrc(qrUrl); // Устанавливаем его в состояние
};
```

### 3. Убедитесь, что ваш API доступен

Если вы загружаете QR-код из API, убедитесь, что ваш API доступен через HTTPS. iOS и другие браузеры блокируют содержимое, которое не загружается через безопасный протокол.

### 4. Отладка с помощью других инструментов разработчика

Для более детальной отладки попробуйте использовать инструменты разработчика в Safari на iOS. Это может помочь вам увидеть, почему именно возникает ошибка "the operation is insecure".

### Заключение

Сохраняя указанные рекомендации в своем коде и меняя способ загрузки на использование `<a>` с атрибутом `download`, вы сможете улучшить поддержку загрузки как на iOS, так и на других платформах.
Похожие вопросы