[RESOLU] Mon image ne s'affiche plus avec TinyMCE

Mammouth du PHP | 2703 Messages

01 avr. 2024, 22:53

quelle est une url valide d'une image, qui s'affiche bien dans le navigateur ?
quelle est l'url de la page où doit s'afficher l'image ?
quelle est le code html de cette page, au niveau de la balise img ?

Avatar du membre
Mammouth du PHP | 1564 Messages

01 avr. 2024, 22:54

Bizarre, peut être que tu met une URL et que c'est interdit...

Ici, ajoute "[RECHERCHE FREELANCE]" au titre de ton sujet.

Eléphant du PHP | 74 Messages

01 avr. 2024, 23:44

Or 1, je n'ai pas compris ce que tu voulais dire ? Mes images ne s'affiche lorsque j'upload mes images...

Au total, 9 développeurs Symfony ont essayé de m'aider. Je crois que je ne finirai jamais par débloquer mon problème... Et je remercie tout le monde pour le temps passé à essayer de m'aider ! :priere:

Fiverr.com et codeur.com, c'est mort... Je vais voir sur Leboncoin lol... Je n'ai mis aucune URL. Mon projet n'est pas véritablement un projet, j'ai eu un blocage lol...

Merci à tous !
Modifié en dernier par semsem le 02 avr. 2024, 00:24, modifié 1 fois.

Eléphant du PHP | 74 Messages

02 avr. 2024, 00:13

Or 1,

l'url de mon image est "assets/images/"
l'url de la page où doit s'afficher l'image est "127.0.0.1:8000/guide"
le code html de cette page, au niveau de la balise img :
{% extends 'base.html.twig' %}

{% block title %}Guides{% endblock %}

{% block body %}
<div class="container-guide">
    <div class="sidebar">
        <ul>
            <li>
               <h3>Nos guides techniques</h3>
            </li>
        </ul>
        <br>
        <ul>
            {% for category in categories %}
                {% set has_visible_subcategories = false %}
                {% for subcategory in category.getSousCategories() %}
                    {% set has_public_articles_in_subcategory = false %}
                    {% for article in subcategory.getArticles() %}
                        {% if not article.isPrive() %}
                            {% set has_public_articles_in_subcategory = true %}
                        {% endif %}
                    {% endfor %}
                    {% if has_public_articles_in_subcategory or is_granted('ROLE_USER') or is_granted('ROLE_ADMIN') %}
                        {% set has_visible_subcategories = true %}
                    {% endif %}
                {% endfor %}
                {% if has_visible_subcategories %}
                    <li class="category-item" id="category_{{ category.id }}">
                        {{ category.getTitre() }}
                        <ul>
                            {% for subcategory in category.getSousCategories() %}
                                {% set has_public_articles_in_subcategory = false %}
                                {% for article in subcategory.getArticles() %}
                                    {% if not article.isPrive() %}
                                        {% set has_public_articles_in_subcategory = true %}
                                    {% endif %}
                                {% endfor %}
                                {% if has_public_articles_in_subcategory or is_granted('ROLE_USER') or is_granted('ROLE_ADMIN') %}
                                    <li class="subcategory-item" id="subcategory_{{ subcategory.id }}">
                                        <span class="arrow-down">→</span> &nbsp;{{ subcategory.getTitre() }}
                                        <ul style="display: none;">
                                            {% for article in subcategory.getArticles() %}
                                                {% if not article.isPrive() or is_granted('ROLE_USER') or is_granted('ROLE_ADMIN') %}
                                                    <li class="link-item">
                                                        &nbsp;&nbsp;<a href="{{ path('detail_guide', {article:article.id}) }}">
                                                            {{ article.titre }}
                                                            {% if article.isPrive() %}
                                                                {% if is_granted('ROLE_USER') or is_granted('ROLE_ADMIN') %}
                                                                    {% if article.isPrive() == true %}
                                                                        🛡️
                                                                    {% endif %}
                                                                {% endif %}
                                                            {% endif %}
                                                        </a>
                                                    </li>
                                                {% endif %}
                                            {% endfor %}
                                        </ul>
                                    </li>
                                {% endif %}
                            {% endfor %}
                        </ul>
                    </li>
                {% endif %}
            {% endfor %}
        </ul>
    </div>
    <div class="main-content">
{% if article %}
    <h3 class="article-title" id="articleTitle">{{article.titre}}</h3>
            <div class="article-content" id="articleContent">{{article.contenu|raw}}</div>
        <div class="article-date" id="articleDate">Publié le : {{ article.createdAt|date('d/m/Y', 'Europe/Paris') }}</div>

        <br>
        <button onclick="#" class="btn-download-pdf">Télécharger ce guide</button>

{% endif %}
    </div>
</div>
<script>
    document.addEventListener('DOMContentLoaded', function() {
        const subcategories = document.querySelectorAll('.subcategory-item');

        subcategories.forEach(function(subcategory) {
            const arrow = subcategory.querySelector('.arrow-down');
            const subcategoryList = subcategory.querySelector('ul');

            subcategory.addEventListener('click', function() {
                if (subcategoryList.style.display === 'none' || subcategoryList.style.display === '') {
                    subcategoryList.style.display = 'block';
                    arrow.innerHTML = '↓'; // Change la flèche vers le bas
                } else {
                    subcategoryList.style.display = 'none';
                    arrow.innerHTML = '→'; // Change la flèche vers la droite
                }
            });
        });
    });

     document.addEventListener('DOMContentLoaded', function() {
        const btnDownloadPdf = document.querySelector('.btn-download-pdf');

        btnDownloadPdf.addEventListener('click', function() {
            // Sélection du contenu de la div .main-content
            const contenuHtml = document.querySelector('.main-content').innerHTML;

            // Envoi du contenu au serveur Symfony pour la génération du PDF
            fetch('{{ path('telecharger_pdf') }}', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({ contenuHtml: contenuHtml }),
            })
            .then(response => {
                if (!response.ok) {
                    throw new Error('Erreur lors de la génération du PDF');
                }
                return response.blob();
            })
            .then(blob => {
                // Création d'un lien temporaire pour télécharger le PDF
                const url = window.URL.createObjectURL(blob);
                const a = document.createElement('a');
                a.style.display = 'none';
                a.href = url;
                a.download = 'contenu.pdf';
                document.body.appendChild(a);
                a.click();
                window.URL.revokeObjectURL(url);
            })
            .catch(error => {
                console.error('Erreur:', error);
            });
        });
    });
</script>

{% endblock %}
j'ai un balise img qui se met en place automatiquement lors de mon upload

Mammouth du PHP | 2703 Messages

02 avr. 2024, 06:09

https://forum.phpfrance.com/styles/PHPfrance/theme/phpfrance-blanc-logo.png

est une url d'une image

un code html généré par le php, c'est quelque chose comme :
<img src="https://forum.phpfrance.com/styles/PHPfrance/theme/phpfrance-logo.png" alt="PHPfrance" style="max-width:256px; margin-top:-20px;" />

quelle est une url valide d'une image, qui s'affiche bien dans le navigateur ?
quelle est le code html de cette page, au niveau de la balise img ?

Eléphant du PHP | 74 Messages

02 avr. 2024, 09:00

Ah d'accord, je te partage :

une url de mon image :
http://127.0.0.1:8000/guide/assets/images/66057c8f3296b.png
un code html généré par le php :
<img src="assets/images/66057c8f3296b.png" alt="" width="501" height="200">
Voici une code html qui s'affiche correctement (l'ajout d'un "/" avant le assets) :
<img src="/assets/images/66057c8f3296b.png" alt="" width="501" height="200">
Image

PS : L'image gtitop.png que tu vois est une bannière qui doit être affichée en permanence. Cette image est dans le dossier "img" et non dans "images". Dans le dossier "img", j'ai des éléments permanents tels que le logo du header... Le dossier "images" stocke les images que j'upload.

Merci beaucoup pour ton retour ! :priere:

Mammouth du PHP | 2703 Messages

02 avr. 2024, 14:19

quel est le code php qui génère
<img src="/assets/images/66057c8f3296b.png" alt="" width="501" height="200">
?

Eléphant du PHP | 74 Messages

02 avr. 2024, 17:02

Je te présente les 2 fichiers pour mon bundle et mon upload :

J'ai suivi la doc de TinyMCE pour les 2 fichiers et j'ai adapté pour mon projet

Upload.php (vers la fin) :
<?php

/***************************************************
 * Only these origins are allowed to upload images *
 ***************************************************/
$accepted_origins = array("http://127.0.0.1:8000");

/*********************************************
 * Change this line to set the upload folder *
 *********************************************/
$imageFolder = "assets/images/";
$name = uniqid();

if (isset($_SERVER['HTTP_ORIGIN'])) {
  // same-origin requests won't set an origin. If the origin is set, it must be valid.
  if (in_array($_SERVER['HTTP_ORIGIN'], $accepted_origins)) {
    header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']);
  } else {
    header("HTTP/1.1 403 Origin Denied");
    return;
  }
}

// Don't attempt to process the upload on an OPTIONS request
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
  header("Access-Control-Allow-Methods: POST, OPTIONS");
  return;
}

reset($_FILES);
$temp = current($_FILES);
if (is_uploaded_file($temp['tmp_name'])) {
  /*
      If your script needs to receive cookies, set images_upload_credentials : true in
      the configuration and enable the following two headers.
    */
  // header('Access-Control-Allow-Credentials: true');
  // header('P3P: CP="There is no P3P policy."');

  // Sanitize input
  if (preg_match("/([^\w\s\d\-_~,;:\[\]\(\).])|([\.]{2,})/", $temp['name'])) {
    header("HTTP/1.1 400 Invalid file name.");
    return;
  }

  // Verify extension
  if (!in_array(strtolower(pathinfo($temp['name'], PATHINFO_EXTENSION)), array("gif", "jpg", "png"))) {
    header("HTTP/1.1 400 Invalid extension.");
    return;
  }

  // Accept upload if there was no origin, or if it is an accepted origin
  // assets/images/
  $extension = pathinfo($temp['name'], PATHINFO_EXTENSION);
  $filetowrite = $imageFolder . $name . "." . $extension;
  move_uploaded_file($temp['tmp_name'], $filetowrite);

  // Determine the base URL
  $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? "https://" : "http://";
  $baseurl = $protocol . $_SERVER["HTTP_HOST"] . rtrim(dirname($_SERVER['REQUEST_URI']), "/") . "/";

  // Respond to the successful upload with JSON.
  // Use a location key to specify the path to the saved image resource.
  // { location : '/your/uploaded/image/file'}
  echo json_encode(array('location' => $filetowrite));
} else {
  // Notify editor that the upload failed
  header("HTTP/1.1 500 Server Error");
}
articleForm2.html.twig :
{% extends '@EasyAdmin/crud/form_theme.html.twig' %}

{% block ea_text_editor_widget %}
    <textarea id="{{ id }}" name="Article[contenu]" class="trix-content tinymce" role="textbox">{{ data }}</textarea>

    <script src="{{ asset('assets/bundles/tinymce/ext/tinymce/tinymce.min.js') }}"></script>
    <script src="{{ asset('bundles/tinymce/ext/tinymce-webcomponent.js') }}" type="module"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.9.3/html2pdf.bundle.min.js"></script>

    <script>
        tinymce.init({
            selector: '.tinymce',
            width: '1000px',
            plugins: 'anchor autolink charmap codesample emoticons image link lists media searchreplace table visualblocks wordcount checklist mediaembed casechange export formatpainter pageembed linkchecker a11ychecker tinymcespellchecker permanentpen powerpaste advtable advcode editimage tinycomments tableofcontents footnotes mergetags autocorrect typography inlinecss',
            toolbar: 'undo redo | blocks fontfamily fontsize | bold italic underline strikethrough | link image media table mergetags | addcomment showcomments | spellcheckdialog a11ycheck typography | align lineheight | checklist numlist bullist indent outdent | emoticons charmap | removeformat | downloadPdf',
            tinycomments_mode: 'embedded',

            images_upload_handler: (blobInfo, progress) => new Promise((resolve, reject) => {
                const xhr = new XMLHttpRequest();
                xhr.withCredentials = false;
                xhr.open('POST', 'upload.php');

                xhr.upload.onprogress = (e) => {
                    progress(e.loaded / e.total * 100);
                };

                xhr.onload = () => {
                    if (xhr.status === 403) {
                        reject({
                            message: 'HTTP Error: ' + xhr.status,
                            remove: true
                        });
                        return;
                    }

                    if (xhr.status < 200 || xhr.status >= 300) {
                        console.log(xhr);
                        reject('HTTP Error: ' + xhr.status + ' ' + xhr.statusText);
                        return;
                    }

                    const json = JSON.parse(xhr.responseText);

                    if (!json || typeof json.location != 'string') {
                        reject('Invalid JSON: ' + xhr.responseText);
                        return;
                    }

                    resolve(json.location);
                };

                xhr.onerror = () => {
                    reject('Image upload failed due to a XHR Transport error. Code: ' + xhr.status);
                };

                const formData = new FormData();
                formData.append('file', blobInfo.blob(), blobInfo.filename());

                xhr.send(formData);
            }),

            setup: function (editor) {

                              editor.on('init', function () {
editor.insertContent('<img src="/img/gtitop.png" alt="Votre image" style="max-width: 100%;">');
                });

                editor.ui.registry.addButton('downloadPdf', {
                    icon: 'export',
                    tooltip: 'Télécharger en PDF',
                    onAction: function () {
                        const content = tinymce.activeEditor.getContent();
                        const element = document.createElement('div');
                        element.innerHTML = content;

                        html2pdf().from(element).set({ 
                            margin: 1,
                            filename: 'document.pdf',
                            image: { type: 'jpeg', quality: 1 },
                            html2canvas: { scale: 2, logging: true },
                            jsPDF: { unit: 'in', format: 'letter', orientation: 'portrait' }
                        }).save();
                    }
                });
            }
        });
    </script>
{% endblock %}

Mammouth du PHP | 2703 Messages

02 avr. 2024, 17:14

la capture d'écran montre l'affichage d'un article. le dernier code montre la partie gérant l'upload d'une image.
est-ce l'affichage de l'image dans la page affichant un article qui ne fonctionne pas ?
si oui, alors il faut le code php qui génère l'affichage de l'article.
si non, alors, qu'est-ce qui ne fonctionne pas ?

Eléphant du PHP | 74 Messages

02 avr. 2024, 19:39

En faite mon image ne s'affiche pas, ce qu'i s'inscrit en base de donnée c'est ça :
<img src="assets/images/66057c8f3296b.png" alt="" width="501" height="200">
Par hasard, j'ai rajouté un "/" avant le assets dans mon html et j'ai remarqué que l'image s'affichait

Oui, l'image ne s'affiche pas lors que je suis dans l'article/{id} dans ma view

Je te monter ma vue, ou j'affiche mes articles (Tout s'affiche sauf les images) c'est dans le main-content je l'ai affiche :
{% extends 'base.html.twig' %}

{% block title %}Guides{% endblock %}

{% block body %}
<div class="container-guide">
    <div class="sidebar">
        <ul>
            <li>
               <h3>Nos guides techniques</h3>
            </li>
        </ul>
        <br>
        <ul>
            {% for category in categories %}
                {% set has_visible_subcategories = false %}
                {% for subcategory in category.getSousCategories() %}
                    {% set has_public_articles_in_subcategory = false %}
                    {% for article in subcategory.getArticles() %}
                        {% if not article.isPrive() %}
                            {% set has_public_articles_in_subcategory = true %}
                        {% endif %}
                    {% endfor %}
                    {% if has_public_articles_in_subcategory or is_granted('ROLE_USER') or is_granted('ROLE_ADMIN') %}
                        {% set has_visible_subcategories = true %}
                    {% endif %}
                {% endfor %}
                {% if has_visible_subcategories %}
                    <li class="category-item" id="category_{{ category.id }}">
                        {{ category.getTitre() }}
                        <ul>
                            {% for subcategory in category.getSousCategories() %}
                                {% set has_public_articles_in_subcategory = false %}
                                {% for article in subcategory.getArticles() %}
                                    {% if not article.isPrive() %}
                                        {% set has_public_articles_in_subcategory = true %}
                                    {% endif %}
                                {% endfor %}
                                {% if has_public_articles_in_subcategory or is_granted('ROLE_USER') or is_granted('ROLE_ADMIN') %}
                                    <li class="subcategory-item" id="subcategory_{{ subcategory.id }}">
                                        <span class="arrow-down">→</span> &nbsp;{{ subcategory.getTitre() }}
                                        <ul style="display: none;">
                                            {% for article in subcategory.getArticles() %}
                                                {% if not article.isPrive() or is_granted('ROLE_USER') or is_granted('ROLE_ADMIN') %}
                                                    <li class="link-item">
                                                        &nbsp;&nbsp;<a href="{{ path('detail_guide', {article:article.id}) }}">
                                                            {{ article.titre }}
                                                            {% if article.isPrive() %}
                                                                {% if is_granted('ROLE_USER') or is_granted('ROLE_ADMIN') %}
                                                                    {% if article.isPrive() == true %}
                                                                        🛡️
                                                                    {% endif %}
                                                                {% endif %}
                                                            {% endif %}
                                                        </a>
                                                    </li>
                                                {% endif %}
                                            {% endfor %}
                                        </ul>
                                    </li>
                                {% endif %}
                            {% endfor %}
                        </ul>
                    </li>
                {% endif %}
            {% endfor %}
        </ul>
    </div>
    <div class="main-content">
{% if article %}
    <h3 class="article-title" id="articleTitle">{{article.titre}}</h3>
            <div class="article-content" id="articleContent">{{article.contenu|raw}}</div>
        <div class="article-date" id="articleDate">Publié le : {{ article.createdAt|date('d/m/Y', 'Europe/Paris') }}</div>

        <br>
        <button onclick="#" class="btn-download-pdf">Télécharger ce guide</button>

{% endif %}
    </div>
</div>
<script>
    document.addEventListener('DOMContentLoaded', function() {
        const subcategories = document.querySelectorAll('.subcategory-item');

        subcategories.forEach(function(subcategory) {
            const arrow = subcategory.querySelector('.arrow-down');
            const subcategoryList = subcategory.querySelector('ul');

            subcategory.addEventListener('click', function() {
                if (subcategoryList.style.display === 'none' || subcategoryList.style.display === '') {
                    subcategoryList.style.display = 'block';
                    arrow.innerHTML = '↓'; // Change la flèche vers le bas
                } else {
                    subcategoryList.style.display = 'none';
                    arrow.innerHTML = '→'; // Change la flèche vers la droite
                }
            });
        });
    });

     document.addEventListener('DOMContentLoaded', function() {
        const btnDownloadPdf = document.querySelector('.btn-download-pdf');

        btnDownloadPdf.addEventListener('click', function() {
            // Sélection du contenu de la div .main-content
            const contenuHtml = document.querySelector('.main-content').innerHTML;

            // Envoi du contenu au serveur Symfony pour la génération du PDF
            fetch('{{ path('telecharger_pdf') }}', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({ contenuHtml: contenuHtml }),
            })
            .then(response => {
                if (!response.ok) {
                    throw new Error('Erreur lors de la génération du PDF');
                }
                return response.blob();
            })
            .then(blob => {
                // Création d'un lien temporaire pour télécharger le PDF
                const url = window.URL.createObjectURL(blob);
                const a = document.createElement('a');
                a.style.display = 'none';
                a.href = url;
                a.download = 'contenu.pdf';
                document.body.appendChild(a);
                a.click();
                window.URL.revokeObjectURL(url);
            })
            .catch(error => {
                console.error('Erreur:', error);
            });
        });
    });
</script>

{% endblock %}
Voici la page :

Image

Mammouth du PHP | 2703 Messages

02 avr. 2024, 19:47

resolve(json.location);
quel est le code de cette fonction ?

Mammouth du PHP | 2703 Messages

02 avr. 2024, 19:56

ou remplacer
echo json_encode(array('location' => $filetowrite));
par
echo json_encode(array('location' => "/".$filetowrite));

Eléphant du PHP | 74 Messages

02 avr. 2024, 20:04

Alors pour cette partie, j'ai suivi la doc tout bêtement, je n'ai pas envie de te dire des bêtises... :

Dans la partie : "Example: using images_upload_handler"

https://www.tiny.cloud/docs/tinymce/6/f ... ge-upload/

Je suis tellement démoralisé, j'ai tout essayé...

A la base TinyMCE save les images en base64, comme c'est pas bon pour la BDD y'a 400 lignes de code par image... Du coup j'ai mis en place ça pour stocker les images, un moment j'avais réussi...

ou remplacer
echo json_encode(array('location' => $filetowrite));
par
echo json_encode(array('location' => "/".$filetowrite));

J'avais déjà essayer ça mais sans succès je vais le faire quand même

Eléphant du PHP | 74 Messages

02 avr. 2024, 20:06

Non ça ne fonctionne pas, cela n'a rien changer... le "/" n'apparaît même pas dans le html... Je suis désolé...

Mammouth du PHP | 2703 Messages

02 avr. 2024, 20:09

après avoir uploadé une nouvelle image ?