OK, donc la piste des larmes pour montrer les images du rapport CR sur le web est la suivante :
1) On suppose ce qui suit :
a) CR 2008 aka CR 12. Je ne connais pas les versions antérieures, mais XIR2 (11.5) peut fonctionner.
b) L'affichage sur le web des images dans les rapports est souhaité, avec développement et prévisualisation sur le poste de travail local.
c) IIS, application ASP.NET, .NET 4.0
d) Crystal Reports est correctement installé (c'est une toute autre discussion, mais il suffit de dire que vous devez avoir un dossier nommé aspnet_client avec les sous-répertoires suivants :
**system_web
4_0_30319
crystalreportviewers12**
etc.
qui est parallèle à l'emplacement de l'application web. Il y en a beaucoup plus - mais pas ici...
e) Les images sont des photos ou autres, mais leur taille est raisonnable et elles ne sont pas trop volumineuses en termes d'octets.
f) Des vignettes pour chaque image existent, ou un fichier de vignettes par défaut est disponible.
g) Il s'agit d'images JPG, PNG ou BMP. Sinon, vous n'avez pas de chance AFAICT. S'il s'agit de documents tels que Word, PDF, etc. que vous souhaitez afficher dans la même liste, vous aurez besoin d'une vignette pour ceux-ci également. Mais restons sur le sujet des images...
h) Vous avez des images organisées dans une hiérarchie de dossiers sur votre serveur web, ou accessibles à votre serveur web, mais en tout cas, accessibles au site web. Supposons qu'elles se trouvent toutes sous un emplacement principal D:\MyDocuments
JE N'AI PAS ESSAYÉ CETTE RÉFÉRENCE À UN SITE FTP COMME LA QUESTION ORIGINALE MAIS JE DOUTE QUE CELA FONCTIONNE.
2) Vous avez besoin d'une table de base de données ou d'un autre type de référentiel accessible au serveur web pour enregistrer vos images. Le format de la base de données est flexible, mais nous supposerons qu'il s'agit d'une liste avec des clés pour votre principal domaine d'intérêt, où vous avez 0:N images par élément principal, par exemple, des photos d'une résidence, ou des photos d'un pont, ou des photos d'une inspection de maison. Cette table comporte soit un chemin d'accès complet à vos fichiers, soit un chemin d'accès relatif, soit un emplacement de dossier plus une colonne dédiée au nom du fichier. Peu importe, mais ils doivent faire un chemin de fichier comme :
D:\MyDocuments\folderA\folder1\area51\whatever\myfile.png
La base de données contient donc l'ensemble, ou une partie, ou les bits, ou autre.
3) Le dossier racine est D:\MyDocuments lors de la visualisation des rapports en local/standalone/non avec un navigateur. C'est un nom arbitraire mais gardez-en la trace pour l'instant.
4) Vous enregistrez ce dossier racine pour que CR puisse le trouver. Cela peut être soit câblé dans vos rapports (mauvais), soit recherché dans un fichier INI (hummm, OK), soit dans un champ de base de données (pourquoi pas, puisque vous enregistrez vos images de toute façon ?), soit passé comme paramètre à vos rapports qui veulent montrer des images ou des liens vers des documents (simple, mais que se passe-t-il lorsque vous déployez sur un autre système de fichiers ?)
5) Dans votre rapport qui montre les images, et je suppose ici N / élément d'intérêt comme décrit dans (2) ci-dessus, vous avez une image insérée avec le concepteur CR. Liez-la à une image vraiment bidon ou à une image par défaut pour pouvoir dire si vous résolvez les noms de fichiers.....
6) La photo de la vignette est récupéré dans la base de données et assemblé si nécessaire, avec des BACK SLASHES, en un nom de fichier. Il sera stocké dans un StringVar partagé FullQualifiedThumbnailFileName (disons) dans le rapport et consiste en la racine du document, que vous avez rendue disponible au rapport à l'étape (4) et stockée dans une StringVar DocRoot partagée dédiée (disons) PLUS le nom du fichier calculé. Ainsi, le champ de formule Nom de fichier de vignette entièrement qualifié ressemble à : {@DocRoot} & FolderLocationFromDB & ThumbnailFileNameFromDB ou dans la vie réelle :
D:\MyDocuments\folderA\folder1\area51\whatever\tn_myfile.png
7) Vous avez maintenant un nom de fichier de vignette. Déposez-la n'importe où sur votre projet de rapport afin de pouvoir voir ce qu'elle résout aussi pendant la conception. Faites exactement la même chose pour vous référer au VRAI nom de fichier et créez une variable appelée Nom de fichier de vignette entièrement qualifié . Il devrait pouvoir être ouvert avec une visionneuse d'images s'il a été construit correctement. Déposez-le aussi quelque part pour que vous puissiez le lire et l'utiliser pour tester.
8) Cliquez avec le bouton droit de la souris sur l'objet image du rapport, choisissez Format Graphic, cliquez sur l'onglet image et ouvrez l'icône de formule pour l'emplacement de l'image.
Avant de commencer à vous plaindre, jetez un coup d'œil aux hypothèses en haut de la page. Je n'ai aucune idée des versions antérieures de CR qui supportent cela, ou si elles le font différemment.
Ensuite, dans l'éditeur de formule, entrez ce qui suit :
{@FullQualifiedThumbnailFileName} que vous avez créé il y a juste une minute. Votre vignette est un chemin d'accès Windows DOS vers un nom de fichier local sur le serveur Web ou sur votre poste de travail de développement.
9) Ajoutez maintenant un paramètre à votre rapport, ou créez une variable de formule, ou autre, qui consiste par défaut en la chaîne "file://". Cette chaîne sera remplacée au moment de l'exécution par l'application httpContext.Current.Session Root, mais nous y reviendrons dans une minute. Je suppose que vous auriez pu faire cela plus tôt.... Nommez ceci WebURLRoot
10) Créez un champ de formule appelé txtImageURL Bref, le nom est à vous, mais devinez ce qui va ici ? Quelque chose comme ceci :
if lowercase( {@WebURLRoot} ) = "file://" THEN
{@WebURLRoot} &
REPLACE( {@txtDocumentFileFullyQualifiedName},"/","\")
else
URLENCODE( {@WebURLRoot} &
REPLACE(
{*DocumentFileNameFromYourSource*}
,"\","/") )
L'ajout du nom de fichier DocumentFileNameFromYourSource à WebURLRoot fonctionne pour moi car j'ai des chemins relatifs dans ma situation qui n'incluent PAS le DocRoot. Votre situation est peut-être différente. En tout cas, dans mode autonome cette variable doit être résolue comme suit :
file://D:\MyDocuments\folderA\folder1\area51\whatever\myfile.png
où il ne s'agit pas d'une vignette. Au moment de l'exécution sur le web, il devrait être résolu en :
http://somewebhost/website/folderA/folder1/area51/whatever/myfile.png
parce que nous allons fournir http://localhost/website à la variable WebURLRoot Je l'ai fait en utilisant un paramètre passé depuis l'application web. Il pourrait être recherché ou câblé mais souvenez-vous, que se passe-t-il si le site web est déplacé ?
Mettez {@txtImageURL} dans la formule de calcul du nom de fichier de l'hyperlien, et cliquez sur l'option pour indiquer qu'il provient d'un site web sur Internet AKA votre serveur de développement local ou autre.
En mode autonome, les chaînes de caractères du fichier en txtImageURL ont des backslashes. Au moment de l'exécution, ils sont remplacés par des barres obliques pour le nom de fichier complet. La fonction URLEncode de Crystal les rend agréables pour le Web.
Encore une baisse txtImageURL sur votre surface de développement jusqu'à ce qu'elle soit droite.
11) Vous avez maintenant un CR RPT avec
a) Une variable contenant la racine Windows de votre arborescence de documents. C:\MyDocuments que vous avez fourni au rapport par n'importe quel moyen. Je le stocke dans la base de données à laquelle mon application se connecte.
b) Une variable contenant le chemin d'accès à votre vignette, construit à partir du nom de la vignette dans la base de données et de la racine du document.
c) Une variable contenant le chemin d'accès Windows à votre nom de fichier réel, construit à nouveau à partir du nom de fichier réel dans la base de données et de la racine du document.
d) Une tige URL de site web qui est file:// pendant le développement y http://localhost/website/ au moment de l'exécution pour le site web. Vous passez ce
e) Une URL de travail pour le fichier image combinant la tige de l'URL du site web avec le fichier réel.
C'est bon jusqu'à présent ? Prends une bière. Peut-être deux.
Changements en C#
1) OK, donc nous devons modifier notre monde pour passer la tige URL du site web à un rapport au moment de l'exécution comme un paramètre. Vous ne pouvez pas le faire sur le Web à l'aide de Crystal Reports Viewer. En supposant que vous ayez suivi l'un des nombreux exemples disponibles sur la façon de charger, paramétrer et afficher un rapport à partir d'une application Web, et je pense que vous pouvez les trouver avec Google, assurez-vous de le faire quelque part dans votre application. J'ai situé le mien dans Global.asax.cs dans l'événement Session_Start qui semble très raisonnable selon l'auteur... Veuillez noter que le crédit est dû à la personne URL référencée... :
// so Crystal can receive the APP_Path as an argument
// Code that runs when a new session is started
// http://aquesthosting.headtreez.com/doc/d9ccf4d8-1873-469e-9dca-815e5854b963
string appPath = System.Web.HttpContext.Current.Request.ApplicationPath.ToLower();
if (appPath == "/") //a site
appPath = "/";
else if (!appPath.EndsWith(@"/")) //a virtual directory i.e. in a subfolder
appPath += @"/";
Session["APP_Path"] = appPath; //stores the value to a session variable for us to use
2) Maintenant, quand vous créez les paramètres pour votre rapport, assurez-vous de passer Session["APP_Path"] comme paramètre, quelque chose comme ceci :
// START CHANGE
// this next check seems unlikely
if(! (HttpContext.Current.Session == null))
{
// pass HttpContext.Current.Session["APP_Path"].ToString() as a parameter
if (!(String.IsNullOrEmpty(HttpContext.Current.Session["APP_Path"].ToString())))// set in Global.asax.cs Start_Session
exporter.Arguments.Add(exporter.Arguments.Count, HttpContext.Current.Session["APP_Path"].ToString()); // to last parameter position
else
exporter.Arguments.Add(exporter.Arguments.Count, String.Empty); // or nothing to last parameter position
// end change
}
où Arguments de l'exportateur contient les paramètres de mes rapports. Votre situation sera sans doute différente. Il est important de placer ce paramètre soit TOUJOURS EN PREMIER, soit TOUJOURS EN DERNIER, de sorte que les autres paramètres ne soient pas perturbés par lui. Utilisez le même ordre pour les paramètres dans le rapport lui-même. Les paramètres associent apparemment des valeurs par nom de toute façon, mais je pense que les mélanger est une mauvaise idée et finit par prêter à confusion.
3) Vous exécutez maintenant vos rapports en mode autonome et, lorsque vous êtes invité à saisir l'URL du site Web, vous entrez les éléments suivants file:// . Lorsque le même rapport est exécuté sur le Web, l'application l'envoie à la tige du site Web, mais quelque chose du genre http://localhost/website/ .
GOTCHAS :
1) Pendant le développement de ce projet, montrez vos variables sur vos rapports. Assurez-vous que pour les vignettes, vous utilisez toujours des chemins relatifs au serveur mais complets pour Windows/DOS, et pour les images, soit des chemins complets pour Windows/DOS pendant le développement, précédés de file://. Vous pouvez toujours les masquer avant la production.
2) Attention aux trop nombreuses barres obliques, etc. Il est facile de se retrouver avec une double barre oblique, ce qui perturbe les URL...
3) Rappelez-vous que les formules sont évaluées dans une sorte de séquence mystique par Crystal, mais je crois savoir que l'en-tête de page est traité avant le détail. Je place TOUTES mes variables communes, c'est-à-dire DocRoot et WebSiteRootURL, dans l'en-tête de page (ou même dans l'en-tête de rapport puisqu'elles ne changent pas), afin qu'elles soient quantifiées en premier et que la bande de détail puisse les utiliser.
4) J'ai délégué l'affichage et le listage des images à un sous-rapport intégré. Il partage les variables dont il a besoin en utilisant un Shared StringVar xyz approche. C'est un peu compliqué, mais en gros, le sous-rapport obtient toujours sa valeur du rapport conteneur pour les éléments communs (voir le commentaire 3 ci-dessus). Pour mettre en place ce sous-rapport, j'ai créé un sous-rapport encore plus petit pour servir de support aux variables communes afin de ne pas avoir à exécuter toute la monstruosité.
5) Ces rapports de "détenteurs de variables" ne peuvent pas être supprimés ou les valeurs ne semblent pas se résoudre. Il faut donc les rendre extrêmement petits et sans bordure, puis écraser les en-têtes de page ou autre pour les cacher. Je suppose que le texte et l'arrière-plan peuvent également être identiques pour les masquer davantage, mais ne le faites pas tant que vous n'avez pas fini de modifier la mise en page, etc. Ce sont les variables de votre mémoire locale.
6) Les fichiers d'images/documents/liens en mode autonome DOIVENT utiliser des chemins de noms de fichiers DOS/Windows conventionnels (sans barres obliques). Ceux-ci peuvent être résolus pour le site web mais pour faire un hyperlien, les barres obliques doivent aller vers l'avant, d'après ce que je sais, donc je suppose que vous devrez faire une volte-face.
7) Accessoirement, j'ai pu déplacer mes documents hors de la hiérarchie du site web pendant le développement en utilisant Junction Magic pour remapper ~/MyDocuments en D:\MyDocuments etc. Le serveur web ne semble pas se soucier du fait qu'il traverse en réalité D:\MyDocuments mais pense qu'il se trouve dans un sous-dossier du site web. CEPENDANT, il se peut que vous deviez utiliser une approche de répertoire virtuel - soyez prévenu. Vous pouvez aussi stocker les documents directement sous le site Web, mais cela semble un peu compliqué.
8) Ai-je mentionné les problèmes de permission ? Non, mais ils pourraient vous mordre. Assurez-vous que le IIS_IUSR et les autres peuvent accéder aux fichiers/dossiers, etc.
9) Tout cela n'aurait-il pas dû être beaucoup plus facile ? Oh bien, merci quand même SAP...
BULLETIN D'INFORMATION -
donc apparemment l'objet Request contient aussi la tige URL du site web. Utilisez-la si vous ne voulez pas suivre la voie d'un global.
De plus, je ne l'ai peut-être pas dit explicitement, mais l'objet CR OLE ne comprend que les conventions de noms de fichiers Windows... et non Unix. En outre, la longueur des chemins doit être conforme. Enfin, lorsque j'affiche les noms de fichiers sur la page Web, j'occulte à la fois la racine DOS/Windows et la racine du site Web et je me contente d'afficher le chemin relatif, par exemple ~/Folder/Folder/File.png, afin qu'il ne soit pas trop évident de savoir comment les documents sont disposés sur le site Web - il s'agit probablement d'une paranoïa inutile, mais elle présente également l'avantage de ne pas déconcerter les utilisateurs en cas de déménagement du site Web.
Les questions peuvent recevoir des réponses ou non. Amusez-vous bien.