Pobieranie pliku ~700mb - problem

Odpowiedz Nowy wątek
2011-07-26 21:20
Duży problem
0

Witajcie, gdy próbuję pobrać plik blisko 700mb o rozszerzeniu *.rar, przy linijce:

while ((iByteSize = streamRemote.Read(byteBuffer, 0, byteBuffer.Length)) > 0)
wywala błąd:

IOException was unhandled by user code
Nie można odczytać danych z połączenia transportowego: Nie można przeprowadzić operacji na gnieździe, ponieważ w systemie brakuje miejsca na bufor lub ponieważ została zapełniona kolejka.

Cały kod:

 private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
 
            string sUrlToReadFileFrom = "ADRES PLIKU";
 
            string sFilePathToWriteFileTo = "C:\\plik.rar";
 
            Uri url = new Uri(sUrlToReadFileFrom);
 
            System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
 
            System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse();
 
            response.Close();
 
            Int64 iSize = response.ContentLength;
 
            Int64 iRunningByteTotal = 0;
 
            using (System.Net.WebClient client = new System.Net.WebClient())
            {
 
                using (System.IO.Stream streamRemote = client.OpenRead(new Uri(sUrlToReadFileFrom)))
                {
 
                    using (Stream streamLocal = new FileStream(sFilePathToWriteFileTo, FileMode.Create, FileAccess.Write, FileShare.None))
                    {
 
                        int iByteSize = 0;
 
                        byte[] byteBuffer = new byte[iSize];
 
                        while ((iByteSize = streamRemote.Read(byteBuffer, 0, byteBuffer.Length)) > 0)
                        {
 
                            streamLocal.Write(byteBuffer, 0, iByteSize);
 
                            iRunningByteTotal += iByteSize;
 
                            double dIndex = (double)(iRunningByteTotal);
 
                            double dTotal = (double)byteBuffer.Length;
 
                            double dProgressPercentage = (dIndex / dTotal);
 
                            int iProgressPercentage = (int)(dProgressPercentage * 100);
 
                            backgroundWorker1.ReportProgress(iProgressPercentage);
 
                        }
 
                        streamLocal.Close();
 
                    }
 
                    streamRemote.Close();
 
                }
 
            }
 
        }
edytowany 1x, ostatnio: madmike, 2016-12-13 18:26

Pozostało 580 znaków

2011-07-26 21:31
0

Pobieraj częściami a nie całość od razu.

Pozostało 580 znaków

2011-07-26 21:36
Duży problem
0

Czyli plik podzielić na części?

Pozostało 580 znaków

2011-07-26 21:50
0

Ściągasz najpierw powiedzmy 1000 MiB, potem kolejne i kolejne aż nie ściągniesz wszystkiego. To co Ci się krzaczy to brak miejsca na bufor. A co by było jak by ktoś chciał ściągnąć np. plik o masie 4 GiB? Masz tyle pamięci by pomieścić taki bufor?

Pozostało 580 znaków

2011-07-26 22:07
ŁF
0
Duży problem napisał(a)

plik blisko 700mb (...) wywala błąd (...) ponieważ w systemie brakuje miejsca na bufor (...)

 
// ...
Int64 iSize = response.ContentLength;
// ...
byte[] byteBuffer = new byte[iSize];

while ((iByteSize = streamRemote.Read(byteBuffer, 0, byteBuffer.Length)) > 0)
// ...


kiedy wy się nauczycie czytać ze zrozumieniem... BTW chyba miałeś na myśli MB (megabajty), a nie mb (milibity).

 > ##### winerfresh napisał(a)
> Ściągasz najpierw powiedzmy 1000 MiB
a nie przypadkiem 10kB?

Osoba, która znajdzie praktyczne zastosowanie milibitów powinna dostać Nobla z budyniu. - somekind 2011-07-27 01:40
i uśmiech prezesa odciśnięty w betonie - ŁF 2011-07-27 11:33

Pozostało 580 znaków

2011-07-28 12:10
To znowu ja
0

Zmniejszyłem do 150mb, dwa pliki pobralo, za trzecim - brak miejsca na bufor.
Ech ;<
Da się to jakoś obejść?

Pozostało 580 znaków

2011-07-28 13:18
ŁF
0

da się i rozwiązanie już zostało podane. użyj bufora o rozmiarze 8-64kB (ewentualnie trochę więcej, ale jest to o tyle bezcelowe, że rozmiar pakietu nie jest tak duży).


edytowany 1x, ostatnio: ŁF, 2011-07-28 13:19

Pozostało 580 znaków

2011-07-28 13:20
ssNah
0

Zrzucaj na dysk, nie twórz za każdym razem nowego strumienia. Co za różnica czy buffor dostaje naraz 700MB danych czy wciskasz do niego 3 strumienie po 150.

Pozostało 580 znaków

2011-07-28 15:32
Duży problem
0

A jak zmienić rozmiar tego bufora?
Domyśliłem się, że chodzi o:

byte[] byteBuffer = new byte[iSize];

Zmieniłem na:

byte[] byteBuffer = new byte[51200000];

Pobiera, jednak przed końcem wyrzuca ten sam błąd, przepełniony bufor.

Pozostało 580 znaków

2011-07-28 15:58
1

ZIOM!
Zatrzymaj się na chwilę i zastanów. Czym jest bufor? Co to takiego właściwie?
http://pl.wikipedia.org/wiki/Bufor_%28programowanie%29

Algorytm wygląda tak:

  1. Tworzę mały bufor
  2. Pobieram do tego bufora tyle ile się w nim mieści
  3. Czy pobrałem wszystko? Jeśli tak, skocz do punktu 5
  4. Jeśli nie, wyczyść bufor (na przykład zrzucając zawartość do pliku - NIE DO INNEJ ZMIENNEJ W PAMIĘCI, chyba że masz jakąś nieskończenie wielką tablicę (nie masz)) i wróc do punktu 2
  5. Zakończ pobieranie, sprawdź czy wielkość powstałego pliku == wszystkim pobranym bajtom (które mogłeś zliczać w międzyczasie lub pobrać to info z nagłówka http)

Nie możesz ot tak sobie zwiększać rozmiaru bufora w nieskończoność, bo po prostu nie masz tyle pamięci. Nie możesz zmniejszyć rozmiaru bufora, nie zmieniająć algorytmu tak, by pobierał po kawałkach....

Nie zapomnij też o obsłużeniu sytaucji, gdy ostatnia partia danych nie zajmuje całego bufora.

edytowany 1x, ostatnio: aurel, 2011-07-28 15:59
popatrzyłaś na kod? tam wystarczy zmienić new byte[multum] na new byte[16*1024] i będzie śmigać - ŁF 2011-07-28 17:17
Z takim podejściem dydaktycznym powinnaś być nauczycielem. :) - somekind 2011-07-28 18:21
Nie patrzyłam na kod :P Ale jak widzę, że ziom deklaruje bufor na 50MB to wiem, że coś się dzieje ;) Nie powinnam być nauczycielem. - aurel 2011-07-28 18:49

Pozostało 580 znaków

2011-07-28 17:19
ŁF
0

napisałem:

ŁF napisał(a)

da się i rozwiązanie już zostało podane. użyj bufora o rozmiarze 8-64kB (ewentualnie trochę więcej, ale jest to o tyle bezcelowe, że rozmiar pakietu nie jest tak duży).

zrozumiałeś:

Duży problem napisał(a)

Zmieniłem na:

byte[] byteBuffer = new byte[51200000];

jesteś wtórnym analfabetą. nie obrażam. stwierdzam fakt.


edytowany 1x, ostatnio: ŁF, 2011-07-28 17:21
pokolenie C#... - Spine 2011-07-28 18:27
Raczej pokolenie leni z dostępem do internetu. - somekind 2011-07-28 19:02
ech, nie wiem, do perełek to chyba się tylko nadaje - ŁF 2011-07-29 12:11

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0