2016-04-24 12 views
2

In Controller habe ich so etwas wie diese:Seltsames Verhalten über gerenderte Datei der Größe

respond_to do |format| 
    format.ini do 
    response.headers['Content-Disposition'] = "attachment; filename=somefile.ini" 
    render ini: SomeClass.make_ini(data) 
    end 
end 

SomeClass.make_ini(data) macht die richtige INI-Datei (1,5 MB) für API-Nutzer. Es gibt eine Aufgabe von unseren Kunden, Content-Length Header hinzuzufügen. Der Grund ist egal.

Wenn ich versuche:

respond_to do |format| 
    format.ini do 
    file = SomeClass.make_ini(data) 
    response.headers['Content-Length'] = file.size.to_s 
    response.headers['Content-Disposition'] = "attachment; filename=somefile.ini" 
    render ini: file 
    end 
end 

file.size.to_s bringt 1301761. Nach der Einstellung Content-Length beträgt die gerenderte Datei 1,2 MB. Und Inhalt wird geschnitten.

Ich wäre dankbar, wenn jemand den Grund sagen könnte.

+1

Wenn Sie curl verwenden, erhalten Sie immer noch das gleiche abgeschnittene Ergebnis? Ist die 'Content-Length' im Header per Curl auch wie erwartet? –

Antwort

5

Es scheint, dass Sie Zeichen in der Datei haben, die mehr als 1 Byte zum Speichern benötigt. Sie sollten die Methode bytesize statt der Größe verwenden.

Sie können ein Beispiel für das Problem finden, das Sie verwenden Größe statt bytesize here. size gibt die Anzahl der Zeichen zurück, aber Sie möchten die Anzahl der Bytes, die von der Methode bytesize zurückgegeben werden.

UTF-8 verwendet zwischen 1 und 4 Bytes zum Speichern der Zeichen.

+0

Vielen Dank, richtiger Weg –

+0

Aber 'size' ist eine Methode für ein File-Objekt und kein String-Objekt, also sollte es nicht die Anzahl der Zeichen zurückgeben, sondern die Anzahl der Bytes, nein? Was * ist * SomeClass.make_ini zurück? –

+0

Ich würde sagen, dass es eine Zeichenfolge zurückgibt, die mit INI-Format gerendert wird. Also Dateivariable es ist keine Datei, sondern eine Zeichenfolge mit dem Inhalt der Datei .ini zurückgegeben. Ich würde sagen, dass Sie eine Zeichenfolge an die Renderfunktion senden müssen, keine Datei. –

2

Unter der Annahme, dass SomeClass.make_iniFile Klasse eine Instanz von Rubys zurückgibt, seine size Methode sollte die Anzahl der Bytes zurückgeben, nicht die Anzahl der Zeichen:

:001 > File.write('japanese.txt', "ルビー") 
=> 9 
:002 > file = File.new('japanese.txt') 
=> #<File:japanese.txt> 
:003 > file.size 
=> 9 

Könnte es sein, dass Sie den Inhaltstyp zu setzen haben in der Antwortkopf?