Java: lecture d'un fichier pdf à partir de L'URL dans Byte array / ByteBuffer dans un applet

j'essaie de comprendre pourquoi ce code ne fonctionne pas pour moi. J'ai une applet qui est censé lire un .pdf et l'afficher avec une bibliothèque pdf-renderer, mais pour une raison quelconque quand je lis dans le .pdf fichiers qui se trouvent sur mon serveur, ils finissent par être corrompu. Je l'ai testé en réécrivant les fichiers.

j'ai essayé de visualiser l'applet dans IE et Firefox et les fichiers corrompus se produisent. La chose drôle est, quand j'essaie de visualisation l'applet dans Safari (pour Windows), le fichier est effectivement très bien! Je comprends que le JVM puisse être différent, mais je suis toujours perdu. J'ai compilé en Java 1.5. Les JVM sont de 1,6. Le morceau qui lit le fichier est ci-dessous.

public static ByteBuffer getAsByteArray(URL url) throws IOException {
        ByteArrayOutputStream tmpOut = new ByteArrayOutputStream();

        URLConnection connection = url.openConnection();
        int contentLength = connection.getContentLength();
        InputStream in = url.openStream();
        byte[] buf = new byte[512];
        int len;
        while (true) {
            len = in.read(buf);
            if (len == -1) {
                break;
            }
            tmpOut.write(buf, 0, len);
        }
        tmpOut.close();
        ByteBuffer bb = ByteBuffer.wrap(tmpOut.toByteArray(), 0,
                                        tmpOut.size());
        //Lines below used to test if file is corrupt
        //FileOutputStream fos = new FileOutputStream("C:abc.pdf");
        //fos.write(tmpOut.toByteArray());
        return bb;
}

je dois rater quelque chose, et je me suis cogné la tête en essayant de comprendre. Toute aide est grandement appréciée. Grâce.


modifier: Pour clarifier davantage ma situation, la différence dans le fichier avant que je lise puis avec le snippet et après, est que ceux que je sors après avoir lu sont significativement plus petits que ce qu'ils sont à l'origine. En les ouvrant, ils ne sont pas reconnus comme .les fichiers pdf. Il n'y a aucune exception levée que j'ignore, et j'ai essayé de rinçage en vain.

cet extrait fonctionne en Safari, ce qui signifie que les fichiers sont lus dans leur intégralité, sans différence de taille, et peuvent être ouverts avec n'importe lequel .lecteur de pdf. Dans IE et Firefox, les fichiers finissent toujours par être corrompu, toujours la même taille plus petite.

j'ai surveillé la variable len (lors de la lecture d'un fichier de 59kb), en espérant voir combien d'octets sont lus à chaque boucle. Dans IE et Firefox, à 18kb, la dans.read(buf) retourne -1 comme si le fichier est terminée. Safari ne fait pas ça.

je vais continuer, et j'apprécie toutes les suggestions jusqu'à présent.

7
demandé sur OscarRyz 2009-03-12 04:49:59

3 réponses

juste au cas où ces petits changements feraient une différence, essayez ceci:

public static ByteBuffer getAsByteArray(URL url) throws IOException {
    URLConnection connection = url.openConnection();
    // Since you get a URLConnection, use it to get the InputStream
    InputStream in = connection.getInputStream();
    // Now that the InputStream is open, get the content length
    int contentLength = connection.getContentLength();

    // To avoid having to resize the array over and over and over as
    // bytes are written to the array, provide an accurate estimate of
    // the ultimate size of the byte array
    ByteArrayOutputStream tmpOut;
    if (contentLength != -1) {
        tmpOut = new ByteArrayOutputStream(contentLength);
    } else {
        tmpOut = new ByteArrayOutputStream(16384); // Pick some appropriate size
    }

    byte[] buf = new byte[512];
    while (true) {
        int len = in.read(buf);
        if (len == -1) {
            break;
        }
        tmpOut.write(buf, 0, len);
    }
    in.close();
    tmpOut.close(); // No effect, but good to do anyway to keep the metaphor alive

    byte[] array = tmpOut.toByteArray();

    //Lines below used to test if file is corrupt
    //FileOutputStream fos = new FileOutputStream("C:\abc.pdf");
    //fos.write(array);
    //fos.close();

    return ByteBuffer.wrap(array);
}

vous avez oublié de fermer fos , ce qui peut raccourcir le dossier si votre demande est toujours en cours d'exécution ou si elle est brusquement interrompue. En outre, j'ai ajouté la création du ByteArrayOutputStream avec la taille initiale appropriée. (Sinon, Java devra attribuer à plusieurs reprises un nouveau tableau et copier, attribuer un nouveau tableau et copier, ce qui est coûteux.) Remplacer la valeur 16384 par une valeur plus valeur appropriée. 16k est probablement petit pour un PDF, mais je ne sais pas comment, mais la taille "moyenne" est que vous attendez de télécharger.

puisque vous utilisez toByteArray() deux fois (même si une est dans le code de diagnostic), j'ai assigné cela à une variable. Enfin, bien que cela ne devrait pas faire de différence, lorsque vous enveloppez le tableau entier dans un ByteBuffer, vous n'avez besoin de fournir le tableau byte lui-même. Fournir l'offset 0 et la longueur est redondante.

notez que si vous téléchargez des fichiers PDF large de cette façon, assurez-vous que votre JVM fonctionne avec un tas assez grand que vous avez assez de place pour plusieurs fois la plus grande taille de fichier que vous vous attendez à lire. La méthode que vous utilisez garde tout le fichier en mémoire, ce qui est correct tant que vous pouvez vous permettre cette mémoire. :)

11
répondu Eddie 2009-03-12 05:17:02

je pensais que j'avais le même problème que toi, mais il s'est avéré que mon problème était que je pensais que tu avais toujours le tampon complet jusqu'à ce que tu n'aies rien. Mais vous ne le supposez pas. Les exemples sur le net (par exemple java2s/tutoriel ) utilisent un BufferedInputStream. Mais cela ne fait aucune différence pour moi.

vous pouvez vérifier si vous obtenez réellement le fichier complet dans votre boucle. Que le problème serait dans le ByteArrayOutputStream.

0
répondu openCage 2010-05-03 17:23:00

avez-vous essayé un flush() avant de fermer le flux tmpOut pour vous assurer que tous les octets sont écrits?

0
répondu Magnilex 2015-01-28 16:43:20