FWIW, я упомяну, что наша установка похожа на то, что описал г-н Matt. Каждый dev заставляет его собственную персональную песочницу смешивать с с ее собственным веб-сервером и DB. На грани выпуска управляемый версией код, создают снимки/переходят и перемещенный в сервер подготовки, который, как предполагается, подражает реальной продуктивной среде максимально тесно. Тестирование следует, тогда выпуск сделан к продуктивной среде.
Для моих собственных персональных (non-work-related) проектов, я разрабатываю локально, тогда продвигаю живой. Один или два проекта могут иметь посреднический сервер/среду тестирования между разработкой и общедоступный/живой.
Да, заголовок Content-Length предоставит вам желаемый индикатор выполнения!
If this really is text/plain
content, you should seriously consider sending it with Content-Encoding: gzip
whenever a client indicates they can handle it. You ought to see huge bandwidth savings. Additionally, if this is a static file, what you really want to do is use sendfile(2)
. As for browsers not doing what you expect in terms of downloading things, you might want to look at the Content-Disposition
header. So anyhow, the logic goes like this:
If the client indicates they can handle gzip
encoding via the Accept-Encoding
header (e.g. Accept-Encoding: compress;q=0.5, gzip;q=1.0
or Accept-Encoding: gzip;q=1.0, identity; q=0.5, *;q=0
or similar) then compress the file, cache the compressed result somewhere, write the correct headers for the response (Content-Encoding: gzip
, Content-Length: n
, Content-Type: text/plain
, etc), and then use sendfile(2)
(however that may or may not have been made available in your environment) to copy the content from the open file descriptor into your response stream.
If they don't accept gzip
, do the same thing, but without gzipping first.
Alternatively, if you have Apache, Lighttpd, or similar acting as a transparent proxy in front of your server, you could use the X-Sendfile
header, which is exceedingly fast:
response.setHeader('Content-Type', 'text/plain')
response.setHeader(
'Content-Disposition',
'attachment; filename="' + os.path.basename(fileName) + '"'
)
response.setHeader('X-Sendfile', fileName)
response.setHeader('Content-Length', os.stat(fileName).st_size)
Две большие проблемы с примером кода, который вы опубликовали, заключаются в том, что он не взаимодействует и загружается перед отправкой весь файл в память.
while r != '':
r = fp.read(1024)
request.write(r)
Помните, что Twisted использует кооперативную многозадачность для достижения любого вида параллелизма. Итак, первая проблема с этим фрагментом заключается в том, что это цикл while по содержимому всего файла (который, по вашему мнению, является большим). Это означает, что весь файл будет считан в память и записан в ответ до того, как что-либо может произойти в процессе. В этом случае случается, что « something » также включает передачу байтов из буфера в памяти в сеть, поэтому ваш код также будет удерживать весь файл в памяти сразу и только начнет избавляться после завершения этого цикла.
Итак, как правило, вы не должны писать код для использования в приложении на основе Twisted, которое использует такой цикл для выполнения большой работы. Вместо этого вам нужно выполнять каждую небольшую часть большой работы таким образом, чтобы она взаимодействовала с циклом событий. Для отправки файла по сети лучше всего использовать производителей и потребителей .