从linux上拿文件到本地 服务器下载文件到本地

简介上一篇文章我们学习了如何在netty中搭建一个HTTP服务器,讨论了如何对客户端发送的请求进行处理和响应,今天我们来讨论一下在netty中搭建文件服务器进行文件传输中应该注意的问题 。
文件的content-type客户端向服务器端请求一个文件,服务器端在返回的HTTP头中会包含一个content-type的内容,这个content-type表示的是返回的文件类型 。这个类型应该怎么确认呢?
一般来说,文件类型是根据文件的的扩展名来确认的,根据 RFC 4288的规范,所有的网络媒体类型都必须注册 。apache也提供了一个文件MIME type和扩展名的映射关系表 。
因为文件类型比较多,我们看几个比较常用到的类型如下:
MIME type扩展名image/jpegjpgimage/jpegjpegimage/pngpngtext/plaintxt text conf def list log inimage/webpwebpapplication/vnd.ms-excelxlsapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheetxlsxapplication/msworddocapplication/vnd.openxmlformats-officedocument.wordprocessingml.documentdocxapplication/vnd.openxmlformats-officedocument.presentationml.presentationpptxapplication/vnd.ms-powerpointpptapplication/pdfpdfJDK提供了一个MimetypesFileTypeMap的类,这个类提供了一个getContentType方法,可以根据请求的文件path信息,来推断其MIME type类型:
private static void setContentTypeHeader(HttpResponse response, File file) {MimetypesFileTypeMap mimeTypesMap = new MimetypesFileTypeMap();response.headers().set(HttpHeaderNames.CONTENT_TYPE, mimeTypesMap.getContentType(file.getPath()));}客户端缓存文件对于HTTP的文件请求来说,为了保证请求的速度,会使用客户端缓存的机制 。比如客户端向服务器端请求一个文件A.txt 。服务器在接收到该请求之后会将A.txt文件发送给客户端 。
其请求流程如下:
步骤1:客户端请求服务器端的文件===================GET /file1.txt HTTP/1.1步骤2:服务器端返回文件,并且附带额外的文件时间信息:===================HTTP/1.1 200 OKDate:Mon, 23 Aug 2021 17:52:30 GMT+08:00Last-Modified:Tue, 10 Aug 2021 18:05:35 GMT+08:00Expires:Mon, 23 Aug 2021 17:53:30 GMT+08:00Cache-Control:private, max-age=60一般来说如果客户端是现代浏览器的话,就会把A.txt缓存起来 。在下次调用的时候只需要在head中添加If-Modified-Since,询问服务器该文件是否被修改了即可,如果文件没有被修改,则服务器会返回一个304 Not Modified,客户端得到该状态之后就会使用本地的缓存文件 。
步骤3:客户端再次请求该文件===================GET /file1.txt HTTP/1.1If-Modified-Since:Mon, 23 Aug 2021 17:55:30 GMT+08:00步骤4:服务器端响应该请求===================HTTP/1.1 304 Not ModifiedDate:Mon, 23 Aug 2021 17:55:32 GMT+08:00在服务器的代码层面,我们首先需要返回一个响应中通常需要的日期字段,如Date、Last-Modified、Expires、Cache-Control等:
SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US);dateFormatter.setTimeZone(TimeZone.getTimeZone(HTTP_DATE_GMT_TIMEZONE));// 日期 headerCalendar time = new GregorianCalendar();log.info(dateFormatter.format(time.getTime()));response.headers().set(HttpHeaderNames.DATE, dateFormatter.format(time.getTime()));// 缓存 headerstime.add(Calendar.SECOND, HTTP_CACHE_SECONDS);response.headers().set(HttpHeaderNames.EXPIRES, dateFormatter.format(time.getTime()));response.headers().set(HttpHeaderNames.CACHE_CONTROL, "private, max-age=" + HTTP_CACHE_SECONDS);response.headers().set(HttpHeaderNames.LAST_MODIFIED, dateFormatter.format(new Date(fileToCache.lastModified())));然后在收到客户端的二次请求之后,需要比较文件的最后修改时间和If-Modified-Since中自带的时间,如果没有发送变化,则发送304状态:
FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, NOT_MODIFIED, Unpooled.EMPTY_BUFFER);setDateHeader(response);

推荐阅读