日本免费全黄少妇一区二区三区-高清无码一区二区三区四区-欧美中文字幕日韩在线观看-国产福利诱惑在线网站-国产中文字幕一区在线-亚洲欧美精品日韩一区-久久国产精品国产精品国产-国产精久久久久久一区二区三区-欧美亚洲国产精品久久久久

從linux上拿文件到本地 服務(wù)器下載文件到本地( 二 )

其他HTTP中常用的處理我們討論了文件類(lèi)型和緩存,對(duì)于一個(gè)通用的HTTP服務(wù)器來(lái)說(shuō),還需要考慮很多其他常用的處理,比如異常、重定向和Keep-Alive設(shè)置 。
對(duì)于異常,我們需要根據(jù)異常的代碼來(lái)構(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中為了避免每次請(qǐng)求都建立連接而做的一個(gè)優(yōu)化方式 。在HTTP/1.0中默認(rèn)是的keep-alive是false,在HTTP/1.1中默認(rèn)的keep-alive是true 。如果在header中手動(dòng)設(shè)置了connection:false,則server端請(qǐng)求返回也需要同樣設(shè)置connection:false 。
另外,因?yàn)镠TTP/1.1中默認(rèn)的keep-alive是true,如果通過(guò)HttpUtil.isKeepAlive判斷通過(guò)之后,還需要判斷是否是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)的文件長(zhǎng)度,這個(gè)可以使用file的length方法來(lái)獲?。?br /> RandomAccessFile raf;raf = new RandomAccessFile(file, "r");long fileLength = raf.length();HttpUtil.setContentLength(response, fileLength);然后我們需要根據(jù)文件的擴(kuò)展名設(shè)置對(duì)應(yīng)的CONTENT_TYPE,這個(gè)在第一小節(jié)已經(jīng)介紹過(guò)了 。
然后再設(shè)置date和緩存屬性 。這樣我們就得到了一個(gè)只包含響應(yīng)頭的DefaultHttpResponse,我們先把這個(gè)只包含響應(yīng)頭的respose寫(xiě)到ctx中 。
寫(xiě)完HTTP頭,接下來(lái)就是寫(xiě)HTTP的Content了 。
對(duì)于HTTP傳遞的文件來(lái)說(shuō),有兩種處理方式,第一種方式情況下如果知道整個(gè)響應(yīng)的content大小,則可以在后臺(tái)直接進(jìn)行整個(gè)文件的拷貝傳輸 。如果服務(wù)器本身支持零拷貝的話(huà),則可以使用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,用來(lái)將大文件拆分成為一個(gè)個(gè)的Chunk進(jìn)行傳輸 。
sendFileFuture =ctx.writeAndFlush(new HttpChunkedInput(new ChunkedFile(raf, 0, fileLength, 8192)),ctx.newProgressivePromise());如果向channel中寫(xiě)入ChunkedFile,則需要添加相應(yīng)的ChunkedWriteHandler對(duì)chunked文件進(jìn)行處理 。
pipeline.addLast(new ChunkedWriteHandler());【從linux上拿文件到本地 服務(wù)器下載文件到本地】注意,如果是完整文件傳輸,則需要手動(dòng)添加last content部分:
lastContentFuture = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);如果是ChunkedFile,last content部分已經(jīng)包含在了chunkedFile中,不需要再手動(dòng)添加了 。

推薦閱讀