FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, NOT_MODIFIED, Unpooled.EMPTY_BUFFER);setDateHeader(response);其他HTTP中常用的處理我們討論了文件類型和緩存,對于一個(gè)通用的HTTP服務(wù)器來說,還需要考慮很多其他常用的處理,比如異常、重定向和Keep-Alive設(shè)置 。
對于異常,我們需要根據(jù)異常的代碼來構(gòu)造一個(gè)DefaultFullHttpResponse,并且設(shè)置相應(yīng)的CONTENT_TYPE頭即可,如下所示:
FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, status, Unpooled.copiedBuffer("異常: " + status + "\r\n", CharsetUtil.UTF_8));response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain; charset=UTF-8");重定向同樣需要構(gòu)建一個(gè)DefaultFullHttpResponse,其狀態(tài)是302 Found,并且在響應(yīng)頭中設(shè)置location為要跳轉(zhuǎn)的URL地址即可:
FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, FOUND, Unpooled.EMPTY_BUFFER);response.headers().set(HttpHeaderNames.LOCATION, newUri);Keep-Alive是HTTP中為了避免每次請求都建立連接而做的一個(gè)優(yōu)化方式 。在HTTP/1.0中默認(rèn)是的keep-alive是false,在HTTP/1.1中默認(rèn)的keep-alive是true 。如果在header中手動設(shè)置了connection:false,則server端請求返回也需要同樣設(shè)置connection:false 。
另外,因?yàn)镠TTP/1.1中默認(rèn)的keep-alive是true,如果通過HttpUtil.isKeepAlive判斷通過之后,還需要判斷是否是HTTP/1.0,并顯示設(shè)置keep-alive為true 。
final boolean keepAlive = HttpUtil.isKeepAlive(request);HttpUtil.setContentLength(response, response.content().readableBytes());if (!keepAlive) {response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.CLOSE);} else if (request.protocolVersion().equals(HTTP_1_0)) {response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);}文件內(nèi)容展示處理文件內(nèi)容展示處理是http服務(wù)器的核心,也是比較難以理解的地方 。
首先要設(shè)置的是ContentLength,也就是響應(yīng)的文件長度,這個(gè)可以使用file的length方法來獲?。?br />
RandomAccessFile raf;raf = new RandomAccessFile(file, "r");long fileLength = raf.length();HttpUtil.setContentLength(response, fileLength);然后我們需要根據(jù)文件的擴(kuò)展名設(shè)置對應(yīng)的CONTENT_TYPE,這個(gè)在第一小節(jié)已經(jīng)介紹過了 。
然后再設(shè)置date和緩存屬性 。這樣我們就得到了一個(gè)只包含響應(yīng)頭的DefaultHttpResponse,我們先把這個(gè)只包含響應(yīng)頭的respose寫到ctx中 。
寫完HTTP頭,接下來就是寫HTTP的Content了 。
對于HTTP傳遞的文件來說,有兩種處理方式,第一種方式情況下如果知道整個(gè)響應(yīng)的content大小,則可以在后臺直接進(jìn)行整個(gè)文件的拷貝傳輸 。如果服務(wù)器本身支持零拷貝的話,則可以使用DefaultFileRegion的transferTo方法將File或者Channel的文件進(jìn)行轉(zhuǎn)移 。
sendFileFuture =ctx.write(new DefaultFileRegion(raf.getChannel(), 0, fileLength), ctx.newProgressivePromise());// 結(jié)束部分lastContentFuture = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);如果并不知道整個(gè)響應(yīng)的context大小,則可以將大文件拆分成為一個(gè)個(gè)的chunk,并且在響應(yīng)的頭中設(shè)置transfer-coding為chunked,netty提供了HttpChunkedInput和ChunkedFile,用來將大文件拆分成為一個(gè)個(gè)的Chunk進(jìn)行傳輸 。
sendFileFuture =ctx.writeAndFlush(new HttpChunkedInput(new ChunkedFile(raf, 0, fileLength, 8192)),ctx.newProgressivePromise());如果向channel中寫入ChunkedFile,則需要添加相應(yīng)的ChunkedWriteHandler對chunked文件進(jìn)行處理 。
pipeline.addLast(new ChunkedWriteHandler());注意,如果是完整文件傳輸,則需要手動添加last content部分:
lastContentFuture = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);如果是ChunkedFile,last content部分已經(jīng)包含在了chunkedFile中,不需要再手動添加了 。
以上關(guān)于本文的內(nèi)容,僅作參考!溫馨提示:如遇健康、疾病相關(guān)的問題,請您及時(shí)就醫(yī)或請專業(yè)人士給予相關(guān)指導(dǎo)!
「愛刨根生活網(wǎng)」www.malaban59.cn小編還為您精選了以下內(nèi)容,希望對您有所幫助:- 山大考研上線分
- 解讀夢見裝修別人房子 從夢境變化來看
- 徐崢光頭是脫發(fā)嗎
- excel一行變成上下兩行 把單元格一分為二
- 走遍天下什么為侶450
- 上吐下瀉胃痙攣什么原因
- 夢見天堂
- 夢見河里抓魚的寓意
- 上海俊柯學(xué)校學(xué)費(fèi)
- 頸椎病刮痧有用處嗎
