2010-08-08 9 views
35

J'essaie d'obtenir une image à partir d'un URL en utilisant un flux byte. Mais je reçois ce message d'erreur:Erreur "Ce flux ne prend pas en charge les opérations de recherche" en C#

Ce flux ne prend pas en charge les opérations de recherche.

Ceci est mon code:

byte[] b; 
HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(url); 
WebResponse myResp = myReq.GetResponse(); 

Stream stream = myResp.GetResponseStream(); 
int i; 
using (BinaryReader br = new BinaryReader(stream)) 
{ 
    i = (int)(stream.Length); 
    b = br.ReadBytes(i); // (500000); 
} 
myResp.Close(); 
return b; 

Qu'est-ce que je fais les gars mal?

+0

Une situation similaire a été répondu et peut aider, voir: http://stackoverflow.com/a/43981770/2791237 –

Répondre

63

Vous voulez probablement quelque chose comme ça. Soit vérifier la longueur échoue, ou le BinaryReader fait des recherches dans les coulisses.

HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(url); 
WebResponse myResp = myReq.GetResponse(); 

byte[] b = null; 
using(Stream stream = myResp.GetResponseStream()) 
using(MemoryStream ms = new MemoryStream()) 
{ 
    int count = 0; 
    do 
    { 
    byte[] buf = new byte[1024]; 
    count = stream.Read(buf, 0, 1024); 
    ms.Write(buf, 0, count); 
    } while(stream.CanRead && count > 0); 
    b = ms.ToArray(); 
} 

modifier:

J'ai vérifié à l'aide réflecteur, et il est l'appel à stream.Length qui échoue. GetResponseStream renvoie un ConnectStream et la propriété Length de cette classe renvoie l'exception que vous avez vue. Comme d'autres affiches mentionnées, vous ne pouvez pas obtenir la longueur d'une réponse HTTP de manière fiable, ce qui est logique.

+0

Salut ngoozeff, merci, cela a fait l'affaire! Ça semble fonctionner! – Yustme

+5

La longueur du flux échoue mais la réponse.ContentLength renvoie une longueur valide. – andleer

+0

Vous n'avez pas besoin de l'entrer dans des octets comme celui-ci, cependant, pour une image, si vous voulez l'utiliser comme une image. Voir ma réponse ci-dessous. – vapcguy

0

La longueur d'un flux ne peut pas être lue dans le flux car le destinataire ne sait pas combien d'octets l'expéditeur va envoyer. Essayez de mettre un protocole au-dessus de http et envoyez la longueur en tant que premier élément dans le flux.

5

Si le serveur n'envoie pas de spécification de longueur dans l'en-tête HTTP, la taille du flux est inconnue. Vous obtenez donc l'erreur lorsque vous essayez d'utiliser la propriété Length.

Lisez le flux en plus petits morceaux, jusqu'à ce que vous atteigniez la fin du flux.

6

Vous ne pouvez pas demander de manière fiable une connexion HTTP pour sa longueur. Il est possible que le serveur vous envoie la longueur à l'avance, mais (a) cet en-tête est souvent manquant et (b) il n'est pas garanti qu'il soit correct.

Au lieu de cela, vous devez:

  1. Créer une longueur fixe byte[] que vous passez à la méthode Stream.Read
  2. Créer une List<byte>
  3. Après chaque lecture, appelez List.AddRange pour ajouter le contenu de votre fixe longueur tampon sur votre liste d'octets

Notez que le dernier appel à Read renverra moins que le nombre total d'octets demandé. Assurez-vous que vous n'ajoutez que ce nombre d'octets sur votre List<byte> et non sur l'ensemble byte[], sinon vous aurez des déchets à la fin de votre liste.

+0

Salut, je suis un peu confus maintenant. Comment devrait ressembler mon code alors? – Yustme

+0

@Yustme, 'var buffer = new Liste (); while (true) {octet [] tmpBuffer = nouvel octet [1024]; int bytesRead = br.Read (tmpBuffer, 0, tmpBuffer.length); buffer.AddRange (tmpBuffer.Take (bytesRead)); if (bytesRead strager

+0

Ou utilisez un StreamReader – Justin

10

Utilisez un StreamReader à la place:

HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(url); 
WebResponse myResp = myReq.GetResponse(); 

StreamReader reader = new StreamReader(myResp.GetResponseStream()); 
return reader.ReadToEnd(); 

(note - les déclarations ci-dessus un String au lieu d'un tableau d'octets)

+1

(... qui peut ensuite être converti en un tableau d'octets en utilisant les fonctions fournies par les classes de codage.) – sunside

+0

cela devrait être la réponse acceptée, c'est beaucoup plus pratique que l'autre un! – Couitchy

+0

S'il avait les routines ou le lien sur la façon de l'obtenir à partir d'un StreamReader en octets, ou une image. Sans cela, nous sommes toujours à la case départ, je dirais. Cela ne m'a pas aidé du tout. – vapcguy

0

Avec les images, vous n'avez pas besoin de lire le nombre d'octets du tout .Il suffit de faire ceci:

Image img = null; 
string path = "http://www.example.com/image.jpg"; 
WebRequest request = WebRequest.Create(path); 
req.Credentials = CredentialCache.DefaultCredentials; // in case your URL has Windows auth 
WebResponse resp = req.GetResponse(); 

using(Stream stream = response.GetResponseStream()) 
{ 
    img = Image.FromStream(stream); 
    // then use the image 
}