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?
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.
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)
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:
byte[]
de longueur fixe que vous transmettez à la méthode Stream.Read
List<byte>
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.
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.
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.
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
}
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
.