URLConnection getContentLength() retourne une valeur négative
Voici mon code:
url = paths[0];
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
int length = connection.getContentLength(); //i get negetive length
InputStream is = (InputStream) url.getContent();
byte[] imageData = new byte[length];
int buffersize = (int) Math.ceil(length / (double) 100);
int downloaded = 0;
int read;
while (downloaded < length) {
if (length < buffersize) {
read = is.read(imageData, downloaded, length);
} else if ((length - downloaded) <= buffersize) {
read = is.read(imageData, downloaded, length - downloaded);
} else {
read = is.read(imageData, downloaded, buffersize);
}
downloaded += read;
publishProgress((downloaded * 100) / length);
}
Bitmap bitmap = BitmapFactory.decodeByteArray(imageData, 0,
length);
if (bitmap != null) {
Log.i(TAG, "Bitmap created");
} else {
Log.i(TAG, "Bitmap not created");
}
is.close();
return bitmap;
J'ai regardé ce dans la documentation Java et la longueur est négative pour la raison suivante:
"le nombre d'octets du contenu, ou un nombre négatif si elle est inconnue. Si le contenu >longueur est connue, mais dépasse de Long.MAX_VALUE, un nombre négatif est retourné."
Quelle pourrait être la raison pour cela? Je suis en train de télécharger une image. Je tiens à souligner que c'est la quatrième méthode que je suis en train de télécharger les images. Les trois autres sont mentionnés ici.
Edit:
Comme demandé, voici la méthode complète que j'utilise.
protected Bitmap getImage(String imgurl) {
try {
URL url = new URL(imgurl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
int length = connection.getContentLength();
InputStream is = (InputStream) url.getContent();
byte[] imageData = new byte[length];
int buffersize = (int) Math.ceil(length / (double) 100);
int downloaded = 0;
int read;
while (downloaded < length) {
if (length < buffersize) {
read = is.read(imageData, downloaded, length);
} else if ((length - downloaded) <= buffersize) {
read = is.read(imageData, downloaded, length
- downloaded);
} else {
read = is.read(imageData, downloaded, buffersize);
}
downloaded += read;
// publishProgress((downloaded * 100) /length);
}
Bitmap bitmap = BitmapFactory.decodeByteArray(imageData, 0,length);
if (bitmap != null) {
System.out.println("Bitmap created");
} else {
System.out.println("Bitmap not created");
}
is.close();
return bitmap;
} catch (MalformedURLException e) {
System.out.println(e);
} catch (IOException e) {
System.out.println(e);
} catch (Exception e) {
System.out.println(e);
}
return null;
}
Vous devez vous connecter pour publier un commentaire.
La réponse est simple, la longueur du contenu n'est pas connu. Ou plus précisément, le serveur n'est pas un "Content-Length" tête dans le message de réponse.
Vous devez modifier votre code, afin de ne pas préallouer fixe la taille du tableau d'octets à contenir l'image.
Une alternative est de créer un local
ByteArrayOutputStream
et de copier les octets lus de la prise pour que. Appelez ensuitetoByteArray
de saisir la totalité du tableau d'octets.Si vous pouvez changer le côté serveur, une autre solution consiste à définir le contenu de la longueur de l'en-tête de la réponse. Ceci doit être fait AVANT que vous obtenez le OutputStream pour écrire l'image en octets de la réponse.
Vous code existant est cassé dans un autre rapport. Si vous obtenez une IOException ou une autre exception, le bloc de code sera "sortie anormale" sans fermer la URLConnection. Ceci va entraîner la fuite d'un descripteur de fichier. Pour ce faire trop de fois et votre application ne pourra pas en raison de l'épuisement des descripteurs de fichiers ... ou local, les numéros de port.
Il est préférable d'utiliser un try /finally pour s'assurer que URLConnections, des Sockets, des Ruisseaux et ainsi de suite que d'arrimage des ressources externes sont TOUJOURS fermées.
denial of service
? Voir la réponse ci-dessous concernant le codage de transfert...Par défaut, cette mise en œuvre de HttpURLConnection demande que les serveurs d'utiliser la compression gzip.
Depuis getContentLength() renvoie le nombre d'octets transmis, vous ne pouvez pas utiliser cette méthode pour prédire combien d'octets peut être lu à partir de getInputStream().
Au lieu de cela, lisez ce cours d'eau jusqu'à ce qu'il est épuisé: lors de la lecture() retourne -1.
La compression Gzip peut être désactivée par le paramètre de l'acceptable des codages dans l'entête de la requête:
Donc, essayez ceci:
Source (Performance paragraphe): http://developer.android.com/reference/java/net/HttpURLConnection.html
Il semble que le serveur n'offre pas Content-Length dans ses en-têtes de réponse, avez-vous eu l' Transfer-Encoding=chunked en-tête de de les en-têtes de réponse?
Ma situation est la suivante : j'ai effectuer une HttpURLConnection et d'envisager le serveur de réponse pour moi, le "Content-Length" avec une valeur positive, mais elle n'a pas, alors je me tourne vers
le AndroidHttpClient qui android HttpClient mise en œuvre, effectuer la même demande de nouveau et a obtenu le droit Content-Length.
J'ai utilisé Wireshark à l'analyse des deux demandes, trouvé un peu de différence sur les en-têtes de requête.
la liste d'en-tête qui utilisent AndroidHttpClient :
la demande d'en-tête de la liste qui utilisent HttpURLConnection :
La seule différence avec l'en-tête de requête est Accept-Encoding qui n'est pas ajouté par moi-même, c'était Android paramètre par défaut pour HttpURLConnection, après ça, je l'ai mis à identité puis effectuer la demande à nouveau, ci-dessous l'en-tête complète des piles :
comme vous pouvez le voir, après j'ai mis le Accept-Encoding ' "identité" de remplacer le système de valeur par défaut "gzip", le serveur a fourni "Content-Length" positif, c'est pourquoi AndroidHttpClient pourrait prendre à droite la valeur de Content-Length et HttpURLConnection pas.
la compression gzip de codage peut causer des fragments de réponse qui considèrent par côté serveur, et si le serveur que vous pouvez recevoir des fragments de codage de la réponse, il ne peut pas offrir la Content-Length en-tête, essayez de désactiver gzip comportement acceptable alors voir quelle différence avec que.
Voir ici: http://download.oracle.com/javase/6/docs/api/java/net/URLConnection.html#getContentLength%28%29
Il dit,
Cela signifie simplement d'en-tête ne contient pas le
content-length
champ. Si vous avez de contrôle sur le code serveur. Vous devez définir le contenu-durée en quelque sorte. Quelque chose comme ServletResponse#setContentLengthJe rencontre aussi ce problème dans mon fond d'écran de l'app. Le problème est que votre serveur ne fournit pas Content-Length dans son en-tête http. Voici un instantané sur un normal d'en-tête http avec Content-length.
Je suis à l'aide d'un hôte donc je ne peux pas changer la configuration du serveur. Dans mon application, je me suis dialogue progression de la valeur maximale à une valeur approximative (qui est plus grand que ma vraie taille de fichier) comme ceci:
Vous pouvez également consulter mon exemple complet de code source ici:
Android Dialogue De Progression De L'Exemple.