Pobieranie pliku ~700mb - 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();

                }

            }

        }
0

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

0

Czyli plik podzielić na części?

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?

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?

0

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

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).

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.

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.

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.

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.

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