首页 > 在ASP.NET中跟踪和恢复大文件下载

在ASP.NET中跟踪和恢复大文件下载

在Web应用程序中处理大文件下载的问题一直出了名的困难,因此对于大多数站点来说,如果用户的下载被中断了,它们只能说悲哀降临到用户的身上了。但是我们现在不必这样了,因为你可以使自己的ASP.NET应用程序有能力支持可恢复(继续)的大文件下载。使用本文提供的方法的时候,你可以跟踪下载的过程,这样你就可以处理动态建立的文件--而且要达到这个目标根本不需要旧式的ISAPI动态链接库和非受控的(unmanaged)C++代码。



  为客户端提供从互联网上下载文件的服务最容易了,对吗?仅仅只需要把可下载的文件复制到你的Web应用程序目录中,发布链接并让IIS完成所有相关的工作。但是,文件服务不应该比脖子上的疼痛还要多(还要麻烦),你不希望整个世界都能访问自己的数据,你不希望服务器被数百个静态文件塞满了,你甚至于希望下载临时文件--只有当客户端开始下载后的空闲时间才建立这些文件。



  不幸的是,使用IIS对下载请求的默认的响应是不可能达到这些效果的。因此在一般情况下,为了获得对下载过程的控制权,开发者需要链接到一个定制的.aspx页面,在这个页面中它们检查用户凭证(credential)、建立可以下载的文件并使用下面的代码把该文件推送给客户端:



Response.WriteFile

Response.End()



  而这就是出现真正麻烦的地方。



  有什么问题?



  WriteFile方法看起来非常完美,它使文件的二进制数据流向客户端。但是直到最近我们才知道,WriteFile方法是一个出名的内存占用狂,它把整个文件载入服务器的RAM中来提供服务(实际上它甚至于会占用文件两倍大小的空间)。对于大文件,这会引起服务内存问题,并且可能重复ASP.NET过程。但是在2004年6月微软发布了一个补丁解决了这个问题。这个补丁现在是.NET Framework 1.1补丁包(SP1)的一部分。



  这个补丁引入了TransmitFile方法,它把一个磁盘文件读入到较小的内存缓冲区之后就开始传输该文件。尽管这个方案解决了内存和循环的问题,但是它仍然不能令人满意。你不能控制响应的生命周期。你无法知道下载是否正确地完成了,你没有办法知道下载是否被中断了,并且(如果你建立了临时文件)你也不知道是否应该、以及什么时候可以删除这些文件。更糟的是,如果下载的确失败了,TransmitFile方法又从客户端下次尝试的文件头部开始下载。



  其中一种可能的解决方案--实现后台智能传输服务(BITS)对于多数站点来说是不可行的,因为这会毁掉维持客户端浏览器操作系统独立性而作出的努力。



  令人满意的解决方案的基础还是来自微软用于解决WriteFile引起的内存混乱问题的第一次尝试(见知识库文章812406)。那篇文章演示了智能的大块数据下载过程,它从文件流中读取数据。在服务器把字节块发送给客户端之前,它使用Response.IsClientConnected属性检查客户端是否仍然保持着连接。如果仍然保持连接,它就继续发送流字节,否则就停止,以防止服务器发送不必要的数据。

这就是我们采用的方法,特别是在下载临时文件的时候。在IsClientConnected返回False的情况下,你就知道下载过程被中断了,你应该保存文件;反之,当这个过程成功完成的时候,你就删除临时文件。此外,为了恢复中断了的下载,你需要做的工作是从上次下载尝试过程中客户端连接失败的文件点开始下载。



  HTTP协议和头信息(Header)支持



  HTTP协议支持可以用于处理被中断下载的头信息。使用少量的HTTP头信息,你可以增强自己的下载过程,使它完全遵循HTTP协议规范。这个规范与ranges一起提供恢复被中断的下载所需要的一切信息。



  下面是它的工作方式。首先,如果服务器支持客户端断点续传,它就在初始的响应中发送Accept-Ranges头信息。服务器还发送一个实体标签(entity tag)头信息(ETag),它包含一个唯一的标识字符串。



  下面的代码显示了IIS发送给客户端的用于响应一个初始下载请求的一些头信息,它向客户端传递了被请求的文件的详细信息。



HTTP/1.1 200 OK

Connection: close

Date: Tue, 19 Oct 2004 15:11:23 GMT

Accept-Ranges: bytes

Last-Modified: Sun, 26 Sep 2004 15:52:45 GMT

ETag: "47febb2cfd76c41:2062"

Cache-Control: private

Content-Type: application/x-zip-compressed

Content-Length: 2844011



  在接收这些头信息之后,如果下载被中断了,IE浏览器在后来的下载请求中会把Etag值和Range头信息发送回服务器。下面的代码显示了尝试恢复被中断下载时IE发送给服务器的一些头信息。



GET http://192.168.100.100/download.zip HTTP/1.0

Range: bytes=822603-

Unless-Modified-Since: Sun, 26 Sep 2004 15:52:45 GMT

If-Range: "47febb2cfd76c41:2062"



  这些头信息表明IE缓存了IIS提供的实体标签,并在If-Range头信息中把它发送回服务器了,这是确保下载从准确相同的文件恢复的一种途径。不幸的是,并非所有的浏览器的工作方式都相同。客户端发送的用于验证文件的其它HTTP头信息可能是If-Match、If-Unmodified-Since或者Unless-Modified-Since。很明显,该规范对于客户端软件必须支持哪些头信息,或者必须使用哪些头信息没有明确的规定。因此,有些客户端根本就没有使用头信息,而IE只使用If-Range和Unless-Modified-Since。你最好用代码检查这些信息。采用这种方式的时候,你的应用程序可以在非常高的层次遵循HTTP规范,并可以使用多种浏览器。Range头信息指明了被请求的字节范围--在例子中它是服务器应该恢复文件流的起始点。



  当IIS接收到恢复下载的请求类型时,它发回包含下面的头信息的响应信息:



HTTP/1.1 206 Partial Content

Content-Range: bytes 822603-2844010/2844011

Accept-Ranges: bytes

Last-Modified: Sun, 26 Sep 2004 15:52:45 GMT

ETag: "47febb2cfd76c41:2062"

Cache-Control: private

Content-Type: application/x-zip-compressed

Content-Length: 2021408



  请注意上面的代码与最初的下载请求的HTTP响应有点差别--恢复下载的请求是206而最初下载的请求是200。这表明通过线路传递进来的内容是部分文件。这一次Content-Range头信息指出了被传递字节的精确数量和位置。



  IE对于这些头信息是很挑剔的。如果最初的响应没有包含Etag头信息,IE永远不会尝试恢复下载。我测试过的其它客户端不使用ETag头信息,它们简单得依赖于文件名、请求范围,并使用Last-Modified头信息(如果它们试图验证该文件)。



  深入了解HTTP协议



  前面的部分中显示的头信息对于使恢复下载的解决方案运行来说是足够的,但是它没有完全覆盖HTTP规范。



  在单个请求中,Range头信息可以询问多个范围,这种特性称为"多部分范围(multipart ranges)"。请不要与分段下载(segmented downloading)混淆,几乎所有的下载工具都使用分段下载来提高下载速度。这些工具声称通过打开两个或多个并发的连接(每个连接请求文件的不同范围)提高了下载速度。



  多部分范围的想法并没有开启多个连接,但是它可以使客户端软件可以在单个请求/响应周期中请求某个文件的最前面的十个和最后面的十个字节。



  诚实地说,我从来都没有找到使用这种特性软件片断。但是我拒绝在代码声明中写入"它并不是完全的HTTP兼容的"。略去这个特性必定会触犯墨菲法则(Murphy's Law)。无论如何,多部分范围还是被用于电子邮件传输中,把头信息、普通文本和附件分开。

示例代码



  我们知道了客户端和服务器如何交换头信息以保证可恢复的下载,把这些知识与文件块流的思想结合起来,你就可以给自己的ASP.NET应用程序增加可靠的下载管理能力了。



  获取下载过程的控制权的方法是从客户端截取下载请求、读取头信息并适当地响应。在.NET之前,你必须编写ISAPI(Internet服务器API)应用程序来实现这种功能,但是.NET框架组件提供了一个IHttpHandler接口,在类中实现的时候,它允许你仅仅使用.NET代码就能够截取和处理请求。这意味着你的应用程序对于下载过程有完全控制权和响应性,再也不会涉及或使用IIS的自动化函数。



  示例代码在HttpHandler.vb文件中包含了一个自定义的HttpHandler类(ZIPHandler)。ZipHandler实现了IhttpHandler接口,并且处理对所有.zip文件的请求。



  为了测试示例代码,你需要在IIS中建立一个新的虚拟目录,并把源文件复制到那儿。在该目录中建立一个叫做download.zip的文件(请注意IIS和ASP.NET不能处理大于2GB的下载,因此要确保你的文件没有超过该限制)。配置你的IIS虚拟目录,通过aspnet_isapi.dll映射.zip扩展名。



  HttpHandler类:ZIPHandler



  在ASP.NET中映射了.zip扩展名之后,客户端每次向服务器请求.zip文件的时候,IIS调用ZipHandler类的ProcessRequest方法(见下载代码)。



  ProcessRequest方法首先建立自定义的FileInformation类(见下载代码)的一个实例,它封装了下载的状态(例如进行中、被中断了等等)。示例把download.zip示例文件的路径硬编码到代码中了。如果把这段代码应用于你自己的应用程序,需要修改它来打开被请求的文件。



 

' 使用objRequest检测请求了哪个文件,用该文件打开objFile。

' 例如objFile = New Download.FileInformation(<完整文件名>)

objFile = New Download.FileInformation( _

objContext.Server.MapPath("~/download.zip"))

 



  接下来,程序使用描述的HTTP头信息(如果请求提供了头信息)执行一系列的验证检查。它把每种检查都封装在小型私有函数中,如果验证成功的话就返回True。如果某个验证检查失败了,响应会立即终止,并发送适当的StatusCode值。



 

If Not objRequest.HttpMethod.Equals(HTTP_METHOD_GET) Or Not

objRequest.HttpMethod.Equals(HTTP_METHOD_HEAD) Then

 ' 目前只支持GET和HEAD方法

 objResponse.StatusCode = 501 ' 没有执行

ElseIf Not objFile.Exists Then

 ' 无法找到被请求的文件

 objResponse.StatusCode = 404 ' 没有找到

ElseIf objFile.Length > Int32.MaxValue Then

 ' 文件太大了

 objResponse.StatusCode = 413 ' 请求实体太大

ElseIf Not ParseRequestHeaderRange(objRequest, alRequestedRangesBegin, alRequestedRangesend, _

objFile.Length, bIsRangeRequest) Then

 ' Range请求中包含无用的实体

 objResponse.StatusCode = 400 ' 无用的请求

ElseIf Not CheckIfModifiedSince(objRequest,objFile) Then

 ' 实体没有被修改过

 objResponse.StatusCode = 304 ' 没有被修改过

ElseIf Not CheckIfUnmodifiedSince(objRequest,objFile) Then

 ' 实体在上次被请求的日期之后被修改过

 objResponse.StatusCode = 412 ' 预处理失败

ElseIf Not CheckIfMatch(objRequest, objFile) Then

 ' 实体与请求不匹配

 objResponse.StatusCode = 412 ' 预处理失败

ElseIf Not CheckIfNoneMatch(objRequest, objResponse,objFile) Then

 ' 实体的确与none-match请求匹配。

 ' 响应代码位于CheckIfNoneMatch函数中

Else

 ' 初步检查成功

 



  这些初步检查的函数中的ParseRequestHeaderRange(见下载代码)检查客户端是否请求了文件范围(这意味着是一个局部下载)。如果被请求的范围是无效的(无效范围指超越文件大小或包含不合理数字的范围数值),该方法把bIsRangeRequest设置为True。如果请求了范围,CheckIfRange方法会验证IfRange头信息。



  如果被请求的范围是有效的,代码会计算响应信息的大小。如果客户端请求了多个范围,响应信息大小的数值会包含多部分头部信息长度的数值。



  如果不能确定某个发送的头部信息值,程序将把这个下载请求作为最初请求而不是部分下载来处理,从文件的顶部开始发送一个新的下载流。



 

If bIsRangeRequest AndAlso CheckIfRange(objRequest, objFile) Then

 ' 这是范围请求

 ' 如果Range数组包含多个实体,它还是一个多部分范围请求

 bMultipart = CBool(alRequestedRangesBegin.GetUpperBound(0)>0)

 ' 进入每个范围来获取整个响应长度

 For iLoop = alRequestedRangesBegin.GetLowerBound(0) To alRequestedRangesBegin.GetUpperBound(0)

  ' 内容的长度(这个范围的)

  iResponseContentLength += Convert.ToInt32(alRequestedRangesend( _

iLoop) - alRequestedRangesBegin(iLoop)) + 1

  If bMultipart Then

   ' 如果是多部分范围请求,计算出将发送的中间头信息的长度

   iResponseContentLength += MULTIPART_BOUNDARY.Length

   iResponseContentLength += objFile.ContentType.Length

   iResponseContentLength += alRequestedRangesBegin(iLoop).ToString.Length

   iResponseContentLength += alRequestedRangesend(iLoop).ToString.Length

   iResponseContentLength += objFile.Length.ToString.Length

   ' 49是多部分下载中换行和其它必要的字符的长度

   iResponseContentLength += 49

  End If

 Next iLoop



 If bMultipart Then

  ' 如果是多部分范围请求,

  ' 我们还必须计算出将发送的最后一个中间头信息的长度

  iResponseContentLength +=MULTIPART_BOUNDARY.Length

  ' 8 是破折号和换行符的长度

  iResponseContentLength += 8

 Else

  ' 不是多部分下载,因此我们必须说明初始HTTP头信息的响应范围

  objResponse.AppendHeader( HTTP_HEADER_CONTENT_RANGE, "bytes " & _

  alRequestedRangesBegin(0).ToString & "-" & _

  alRequestedRangesend(0).ToString & "/" & _

  objFile.Length.ToString)

  'End If

  ' 范围响应

  objResponse.StatusCode = 206 ' 局部响应

 Else

  ' 这不是范围请求,或者被请求的范围实体ID与当前的实体ID不匹配,

  ' 因此开始新的下载

  ' 指明文件完成部分的大小等于内容的长度

  iResponseContentLength =Convert.ToInt32(objFile.Length)

  ' 返回正常的OK状态

  objResponse.StatusCode = 200

 End If

 ' 接下来服务器必须发送几个重要的响应头信息,例如内容长度、Etag、和文件的内容类型:

 ' 把内容长度写入响应

 objResponse.AppendHeader( HTTP_HEADER_CONTENT_LENGTH,iResponseContentLength.ToString)

 ' 把最后修改日期写入响应

 objResponse.AppendHeader( HTTP_HEADER_LAST_MODIFIED,objFile.LastWriteTimeUTC.ToString("r"))

 ' 告诉客户端软件我们接受了范围请求

 objResponse.AppendHeader( HTTP_HEADER_ACCEPT_RANGES,HTTP_HEADER_ACCEPT_RANGES_BYTES)

 ' 把文件的实体标签写入响应(用引号括起来)

 objResponse.AppendHeader(HTTP_HEADER_ENTITY_TAG, """" & objFile.EntityTag & """")

 ' 把内容类型写入响应

 If bMultipart Then

  ' 多部分消息有这种特殊的类型

  ' 在例子中文件实际的mime类型在以后才写入响应

  objResponse.ContentType = MULTIPART_CONTENTTYPE

 Else

  ' 单个部分消息拥有的文件内容类型

  objResponse.ContentType = objFile.ContentType

End If

 





  下载所需要的一切都准备好了,可以开始下载文件了。你将使用FileStream对象从文件中读取字节块。把FileInformation实例objFile的State属性设置为fsDownloadInProgress。只要客户端保持连接,服务器就从文件中读取字节块并发送给客户端。对于多部分下载,这段代码会发送特定的头信息。如果客户端中断连接,服务器就把文件状态设置为fsDownloadBroken。如果服务器完成了被请求范围的发送过程,它会把状态设置为fsDownloadFinished(见下载代码)。

FileInformation辅助类



  在ZIPHandler部分中你会发现,FileInformation是一个辅助类,它封装了下载状态信息(例如下载中、中断等等)。



  为了建立FileInformation的实例,你需要把被请求文件的路径传递给该类的构造函数:



Public Sub New(ByVal sPath As String)

 m_objFile = New System.IO.FileInfo(sPath)

End Sub



  FileInformation使用System.IO.FileInfo对象来获取文件的信息,这些信息是作为该对象的属性暴露的(例如文件是否存在、文件全名、大小等等)。这个类还暴露了一个DownloadState枚举,它描述了下载请求的多种状态:



Enum DownloadState

 ' Clear:没有下载过程,文件可能在维护

 fsClear = 1

 ' Locked:动态建立的文件不能被更改

 fsLocked = 2

 ' In Progress:文件被锁定了,下载过程正在进行

 fsDownloadInProgress = 6

 ' Broken:文件被锁定了,下载过程正在进行,但是被取消了

 fsDownloadBroken = 10

 ' Finished:文件被锁定了,下载过程完成了

 fsDownloadFinished = 18

End Enum



  FileInformation还提供了EntityTag属性值。示例代码中的这个值是硬编码的,这是由于示例代码只使用了一个下载文件,并且该文件不会被改变,但是对于实际应用程序来说,你会提供多个文件,甚至于动态地建立文件,你的代码必须为每个文件提供一个唯一的EntityTag值。此外,每次改变或修改该文件的时候,这个值也必须改变。这使客户端软件能够验证它们已经下载的字节块是否仍然是最新的。下面是示例代码中返回硬编码EntityTag值的部分:



Public ReadOnly Property EntityTag() As String

 ' EntityTag用于对客户端的初始(200)响应,以及来自客户端的恢复请求

 Get

  ' 为文件建立唯一的字符串。

  ' 注意,只要文件没有发生改变,该唯一码就必须保留。

  ' 但是,如果文件的确改变了或者被修改了,这个码必须改变。

  Return "MyExampleFileID"

 End Get

End Property



  一个简单的和大致足够安全的EntityTag可能由文件名和文件最后被修改的日期组成。无论使用什么方法,你都必须确保这个值是真的是唯一的,不会与其它文件的EntityTag混淆。我希望在自己的应用程序中按照客户、顾客和邮编索引来动态地替被建立的文件命名,并把用作EntityTag的GUID存储在数据库中。



  ZipFileHandler类读取和设置公共的State属性。在完成下载以后,它把State设置为fsDownloadFinished。这个时候你就可以删除临时文件了。这儿一般需要调用Save方法来维持状态。



Public Property State() As DownloadState

 Get

  Return m_nState

 End Get

 Set(ByVal nState As DownloadState)

  m_nState = nState

  ' 可选操作:这个时候你可以自动地删除文件。

  ' 如果状态被设置为Finished ,你就再也不需要这个文件了。

  ' If nState =DownloadState.fsDownloadFinished Then

   ' Clear()

  ' Else

   ' Save()

  ' End If

  Save()

 End Set

End Property



  在文件状态发生改变的任何时候ZipFileHandler都应该调用Save方法,保存文件的状态,这样在以后才能显示给用户。你还可以用它来保存你自己建立的EntityTag。请不要把文件的状态和EntityTag值保存在Application、Session或Cache中--你必须跨越所有的这些这些对象的生命周期来保存信息。



Private Sub Save()

 ' 把该文件下载的状态保存到数据库或XML文件中。

 ' 当然,如果你并没有动态地建立文件,就不需要保存这个状态。

End Sub



  前面提到,示例代码只处理一个已有的文件(download.zip),但是你可以进一步增强这个程序,根据需要建立被请求的文件。



  测试示例代码的时候,你的本地系统或LAN可能太快了,以至于无法中断下载过程,因此我推荐你使用慢速LAN连接(在IIS中减少站点的带宽是一种模拟的方法)或者把服务器放到互联网上。



  在客户端上下载文件仍然很艰难。ISP操作的不对的或配置错误的Web缓冲服务器都可能使大文件下载过程失败,包括下载状况恶化或早期对话终结。如果文件大小超过了255MB,你就应该鼓励顾客使用第三方下载管理软件,尽管某些最新的浏览器内建了基本的下载管理器。



    如果你希望进一步扩展示例代码,查阅一下HTTP规范是有益的。你可以为下载建立MD5校验值,使用Content-MD5头信息添加它们,提供一种验证下载文件完整性的途径。示例代码除了GET和HEAD之外没有涉及到其它的HTTP方法。

转载于:https://www.cnblogs.com/cuihongyu3503319/archive/2012/05/15/2500841.html

更多相关:

  • 本文来自 运维人生 ,作者:fly是个稻草人链接:http://www.ywadmin.com/?id=76误删除linux系统文件了?不用急,本文将给你一个恢复linux文件的方法,让你轻松应对运维中的各风险问题。方法总比问题多~说在前面的话针对日常维护操作,难免会出现文件误删除的操作。大家熟知linux文件系统不同win有回收...

  • 原文来自SecIN社区—作者:WiHat0x00 什么是WebShell渗透测试工作的一个阶段性目标就是获取目标服务器的操作控制权限,于是WebShell便应运而生。Webshell中的WEB就是web服务,shell就是管理攻击者与操作系统之间的交互。Webshell被称为攻击者通过Web服务器端口对Web服务器有一定的操作权限,而...

  • 断电时文件系统发生了什么?硬盘又发生了什么?下一次开机时写到一半的文件在系统层面还在吗?在底层还在吗?更进一步的, 文件系统如何保证事务性, 会不会存在某种极端情况导致例如最后几个bit还没写完, 文件系统却认为它成功了的情况?回答不限任何文件系统,谢谢!下面是「北极」的回复分享断电的一瞬间,很多事情是无法确定的:1. 你无法确定...

  • 接到项目需求。需要搭建一个页面进行交互,慢慢来b (2).jpg使用python django框架进行页面的搭建在项目文件下打开窗口,输入命令;django-admin startproject helloword#在文件helloword/helloword/创建view.py在view.py文件中输入以代码from django....

  • 常见的错误集合解决方案(一)No.1提示错误'Microsoft.VC90.CRT,version="9.0.21022.8"把Microsoft.NET Framework 3.5.1下面的全部勾选上。No.2解决Qt Designer设计的图标但是VS生成不显示问题描述:在Qt designer中为菜单栏和工具栏设计的图标,但是...

  • 在浏览器中从PyCharm官网下载最新社区版本,它时免费的 https://www.jetbrains.com/pycharm/download/#section=linux 默认存放地址是下载文件夹,然后解压到指定目录 cd ~/下载 sudo tar zxvf pycharm-community-2017.3.2.t...

  • 参考github上项目主页 https://github.com/yu239/PyQvod 该项目的作用是:在Linux下面观看快播视频网站的视频,先下载后观看,比较自动化。 下面记录了实际安装步骤: 目前的思路是,采用windows版本的Qvod下载程序,使用wine运行在Linux下面,所以首先必须安装wine。为了便...

  • 下载地址:网盘下载 本书提供与C语言编程相关的全面资源和深入讨论。本书通过对指针的基础知识和高级特性的探讨,帮助程序员把指针的强大功能融入到自己的程序中去。 全书共18章,覆盖了数据、语句、操作符和表达式、指针、函数、数组、字符串、结构和联合等几乎所有重要的C编程话题。书中给出了很多编程技巧和提示,每章后面有针对性很强的练习,附录...

  • 本文档主要介绍RK3288平台的WiFi&BT配置说明。     下载地址:http://dev.t-firefly.com/thread-13642-1-1.html 更多开发资料请到社区精华系列“资源共享”专栏下载 http://dev.t-firefly.com/forum-263-1.html 转载于:https:/...

  • ​> 之前做过一些文件下载的统计,发现谷歌浏览器chrome和火狐firefox, 一般都是单线程的下载文件,360浏览器却是多线程的下载。 如今切换到了mac上,发现没有360哪个浏览器,就像找个在linux或者mac下能够多线程下载的工具。 linux mac 下载现状 linux一般都是用的命令行下载wget curl尽...

  • 原来我们可以从官网 http://trafficserver.apache.org/tools/via 获取via头的解码信息来得到指定url的缓存状态信息,现在我们可以直接利用本地工具就可以达到目的。 traffic_via工具能够解码Via头信息,输入的参数要求是[]包含的字符串。 使用方法: 参考...

  • 简介 channel_stats插件能对每个channel收集运行时统计信息(速率,请求数,更多选项将在未来添加),这些统计信息通过http json方式输出,这些 接口代码取自stats_over_http插件。通常,该插件只用于具有*固定*个数的remap规则的反向代理服务器,它并非为那些不限制channel的代理服务器,比如op...

  • logger是一个shell命令接口,可以通过该接口使用Syslog的系统日志模块,还可以从命令行直接向系统日志文件写入一行信息 logger语法: 可以使用的相关命令 -d, --udp 使用数据报(UDP)而不是使用默认的流连接(TCP) -i, --id 逐行记录每一次logger的进程ID -f, --fil...

  • 今天在测试中遇到了一个问题 使用JMeter时请求相关地址参数及方法都填写正确,但是相应数据返回始终不对,例如 查看取样器结果显示 200 正常,但响应数据不符合正常的结果。 经反复检查发现问题如下: 1)没有添加HTTP信息头管理器 (获取根据就近原则) 2)HTTP信息头管理器中填写错误,将Content-Type 填写成了Co...

  • 第一,你要有log4j的对应的包,由于我用的maven,所以直接在pom.xml文件依赖下载则可,如你尚为有此包,请自行百度下载导入,或上http://www.mvnrepository.com/搜索。上如则是我的log4j的包的版本。好了,用了jar包之后,用来学习的项目结构如下:在对应的路径下创建log4Test.java和log...