web-dev-qa-db-fra.com

Erreur "Ce flux ne prend pas en charge les opérations de recherche" en C #

J'essaie d'obtenir une image à partir d'une URL à l'aide d'un flux byte. Mais je reçois ce message d'erreur:

Ce flux ne supporte pas 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 de mauvais gars?

40
Yustme

Vous voulez probablement quelque chose comme ça. Soit la vérification de la longueur échoue, soit le lecteur BinaryReader effectue une recherche en coulisse.

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é en utilisant réflecteur, et c'est l'appel à stream.Length qui échoue. GetResponseStream renvoie un ConnectStream et la propriété Length de cette classe lève l'exception que vous avez vue. Comme d'autres affiches l'ont mentionné, vous ne pouvez pas obtenir de manière fiable la longueur d'une réponse HTTP, c'est donc logique.

67
ngoozeff

Utilisez un StreamReader à la place:

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

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

(Remarque - ce qui précède retourne une String au lieu d'un tableau d'octets)

11
Justin

Vous ne pouvez pas demander de manière fiable une longueur à une connexion HTTP. Il est possible de faire en sorte que le serveur vous envoie la longueur à l’avance, mais (a) cet en-tête est souvent manquant et (b) son exactitude n’est pas garantie.

Au lieu de cela, vous devriez:

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

Notez que le dernier appel à Read renverra moins que le nombre total d'octets que vous avez demandé. Assurez-vous d’ajouter ce nombre d’octets à votre List<byte> et non à l’intégralité du byte[], sinon vous aurez des ordures à la fin de votre liste.

6
Tim Robinson

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 morceaux plus petits, jusqu'à la fin du flux.

5
Guffa

La longueur d'un flux ne peut pas être lue à partir du flux car le destinataire ne sait pas combien d'octets l'envoi sera envoyé. Essayez de placer un protocole au-dessus de http et d’envoyer, par exemple, la longueur en tant que premier élément du flux.

0
schoetbi

Avec les images, vous n'avez pas besoin de lire le nombre d'octets. Faites juste 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
}
0
vapcguy

Peut-être devriez-vous utiliser l'API System.Net.WebClient. Si vous utilisez déjà client.OpenRead(url), utilisez client.DownloadData (url)

var client = new System.Net.WebClient();
byte[] buffer = client.DownloadData(url);
using (var stream = new MemoryStream(buffer))
{
    ... your code using the stream ...
}

Évidemment, cela télécharge tout avant que la variable Stream soit créée, de sorte que l'utilisation de la variable Stream peut ne pas être utilisée webClient.DownloadData("https://your.url") obtient un tableau d'octets que vous pouvez ensuite transformer en MemoryStream.

0
James Esh