2011-01-19 24 views
6

Próbuję pobrać duże (600MB) plik binarny do serwera przy użyciu CFHTTP na ColdFusion 8:Pobieranie dużych plików w ColdFusion użyciu CFHTTP

<cfhttp 
    method="get" 
    url="#fileURL#" 
    path="#filePath#" 
    file="#fileName#" 
    timeout="600" 
    getasbinary="auto" 
> 

To działa dobrze dla mniejszych plików (100something MB), ale dla dużego dostaję błąd Server 500: "java.lang.OutOfMemoryError: Przestrzeń sterty Java".

Plik jest pobierany z folderu Dropbox - więc jedyną dostępną opcją jest użycie HTTP GET.

Czy ktoś ma pomysł, jak go pobrać, aby nie zabił serwera ani limitu czasu?

+1

Jeśli jest to plik w Dropbox, dlaczego nie wystarczy zainstalować klienta Dropbox na serwerze, i obejrzeć katalog dla nowych/zaktualizowanych plików? –

+0

Ponieważ mamy kilka oddzielnych klientów na tym samym serwerze - nie można zainstalować wielu klientów Dropbox. Ale dzięki za pomysł Ben. – Lucas

Odpowiedz

14

Możesz to zrobić, wywołując Java z kodu CF. Zbuforowane klasy strumienia wejściowego i wyjściowego są zaprojektowane tak, aby przechowywały porcje danych, a nie całą całość, unikając błędów OutOfMemory.

getByteArray() to metoda pomocnicza, ponieważ nie ma sposobu, aby zadeklarować coś w rodzaju bezpośrednio w wersji byte buf[]=new byte[1024];.

W tym przykładzie zmień zmienne source i destination.

Przykład

<cfset source = 'protocol://domain/path/to/file.ext'> 
<cfset destination = getDirectoryFromPath(getCurrentTemplatePath()) & listlast(source, "/")> 
<cffunction name="getByteArray" access="private" returnType="binary" output="no"> 
    <cfargument name="size" type="numeric" required="true"/> 
    <cfset var emptyByteArray = 
     createObject("java", "java.io.ByteArrayOutputStream").init().toByteArray()/> 
    <cfset var byteClass = emptyByteArray.getClass().getComponentType()/> 
    <cfset var byteArray = 
     createObject("java","java.lang.reflect.Array").newInstance(byteClass, arguments.size)/> 
    <cfreturn byteArray/> 
</cffunction> 

<cfscript> 
uri = createObject("java", "java.net.URL").init(source); 
uis = uri.openStream(); 
bis = createObject("java", "java.io.BufferedInputStream").init(uis); 
fos = createObject("java", "java.io.FileOutputStream").init(destination); 
bos = createObject("java", "java.io.BufferedOutputStream").init(fos); 
buffer = getByteArray(1024); 
len = bis.read(buffer); 
while(len > 0) { 
    bos.write(buffer,0,len); 
    len = bis.read(buffer); 
} 
bos.close(); 
bis.close(); 
fos.close(); 
uis.close(); 
</cfscript> 
+0

Fajne howto, szczególnie dla osób bez tła Java (jak ja). – Sergii

+0

Java doskonale zna się na CF, ponieważ pozwala na obejście niektórych problemów z wbudowaną funkcjonalnością. – orangepips

+0

Dziękuję bardzo orangepips, spróbuję. – Lucas

2

Problem polega na tym, że jest za duży. ColdFusion wczyta całą zawartość do pamięci przed zapisaniem jej na dysku.

Najlepiej będzie, jeśli użyjesz innej metody, aby pobrać plik. wget może wykonywać żądania http z wiersza poleceń. To z rozsądnym użyciem CFEXECUTE jest prawdopodobnie dobrą drogą.

+0

Dzięki za pomysł Al. – Lucas