请求头必须配置如下行:

Content-Type' : 'multipart/form-data; boundary=---12321  boundary=---12321位文件的分界线

body如下:

"-----12321\r\n"        //分割文件时加--
                "Content-Disposition: form-data; name=\"file\"; filename=\"test.txt\"\r\n"
                "Content-Type: text/plain\r\n\r\n"     
                "inc-cd\n" test.txt的文件内容
                "-----12321\r\n"

假设接受文件的网页程序位于 http://192.168.29.65/upload_file/UploadFile.假设我们要发送一个图片文件,文件名为“kn.jpg”,

  首先客户端链接 192.168.24.56 后, 应该发送如下http 请求:

  POST/logsys/home/uploadIspeedLog!doDefault.html HTTP/1.1

  Accept: text/plain, */* 
  Accept-Language: zh-cn 
  Host: 192.168.24.56
  Content-Type:multipart/form-data;boundary=-----------------------------7db372eb000e2
  User-Agent: WinHttpClient 
  Content-Length: 3693
  Connection: Keep-Alive

  -------------------------------7db372eb000e2

  Content-Disposition: form-data; name="file"; filename="kn.jpg"

  Content-Type: image/jpeg

  (此处省略jpeg文件二进制数据...)

  -------------------------------7db372eb000e2--

  此内容必须一字不差,包括最后的回车,红色字体部分就是协议的头。给服务器上传数据时,并非协议头每个字段都得说明,其中,content-type是必须的,它包括一个类似标志性质的名为boundary的标志,它可以是随便输入的字符串。对后面的具体内容也是必须的。它用来分辨一段内容的开始。Content-Length: 3693 ,这里的3693是要上传文件的总长度。绿色字体部分就是需要上传的数据,可以是文本,也可以是图片等。数据内容前面需要有Content-Disposition, Content-Type以及Content-Transfer-Encoding等说明字段。最后的紫色部分就是协议的结尾了。

  注意这一行:

  Content-Type: multipart/form-data; boundary=---------------------------7db372eb000e2  

  根据 rfc1867, multipart/form-data是必须的. 
  ---------------------------7db372eb000e2 是分隔符,分隔多个文件、表单项。其中b372eb000e2 是即时生成的一个数字,用以确保整个分隔符不会在文件或表单项的内容中出现。Form每个部分用分隔符分割,分隔符之前必须加上"--"着两个字符(即--{boundary})才能被http协议认为是Form的分隔符,表示结束的话用在正确的分隔符后面添加"--"表示结束。

  前面的 ---------------------------7d 是 IE 特有的标志,Mozila 为---------------------------71.

  

  每个分隔的数据的都可以用Content-Type来表示下面数据的类型,可以参考rfc1341 (http://www.ietf.org/rfc/rfc1341.txt)

  例如 :Contect-Type:image/jpeg 表示下面的数据是jpeg文件数据

[转]通过 http 协议上传文件

2008-04-30 23:55
1、概述
在最初的 http 协议中,没有上传文件方面的功能。 rfc1867 ( http://www.ietf.org/rfc/rfc1867.txt ) 为 http 协议添加了这个功能。客户端的浏览器,如 Microsoft IE, Mozila, Opera 等,按照此规范将用户指定的文件发送到服务器。服务器端的网页程序,如 php, asp, jsp 等,可以按照此规范,解析出用户发送来的文件。
Microsoft IE, Mozila, Opera 已经支持此协议,在网页中使用一个特殊的 form 就可以发送文件。
绝大部分 http server ,包括 tomcat ,已经支持此协议,可接受发送来的文件。
各种网页程序,如 php, asp, jsp 中,对于上传文件已经做了很好的封装。
2、上传文件的实例:用 servelet 实现(http server 为 tomcat 4.1.24)
1. 在一个 html 网页中,写一个如下的form :
<form enctype="multipart/form-data" action="http://192.168.29.65/UploadFile" method=post>
    load multi files :<br>
    <input name="userfile1" type="file"><br>
    <input name="userfile2" type="file"><br>
    <input name="userfile3" type="file"><br>
    <input name="userfile4" type="file"><br>
    text field :<input type="text" name="text" value="text"><br>
    <input type="submit" value="提交"><input type=reset>
</form>
2. 服务端 servelet 的编写
现在第三方的 http upload file 工具库很多。Jarkata 项目本身就提供了fileupload 包http://jakarta.apache.org/commons/fileupload/ 。文件上传、表单项处理、效率问题基本上都考虑到了。在 struts 中就使用了这个包,不过是用 struts 的方式另行封装了一次。这里我们直接使用 fileupload 包。至于struts 中的用法,请参阅 struts 相关文档。
这个处理文件上传的 servelet 主要代码如下:
public void doPost( HttpServletRequest request, HttpServletResponse response ) {
    DiskFileUpload diskFileUpload = new DiskFileUpload();
    // 允许文件最大长度
    diskFileUpload.setSizeMax( 100*1024*1024 );
    // 设置内存缓冲大小
    diskFileUpload.setSizeThreshold( 4096 );
    // 设置临时目录
    diskFileUpload.setRepositoryPath( "c:/tmp" );
    List fileItems = diskFileUpload.parseRequest( request );
    Iterator iter = fileItems.iterator();
    for( ; iter.hasNext(); ) {
        FileItem fileItem = (FileItem) iter.next();
        if( fileItem.isFormField() ) {
            // 当前是一个表单项
            out.println( "form field : " + fileItem.getFieldName() + ", " + fileItem.getString() );
        } else {
            // 当前是一个上传的文件
            String fileName = fileItem.getName();
            fileItem.write( new File("c:/uploads/"+fileName) );
        }
    }
}
为简略起见,异常处理,文件重命名等细节没有写出。
3、 客户端发送内容构造
假设接受文件的网页程序位于 http://192.168.29.65/upload_file/UploadFile.
假设我们要发送一个二进制文件、一个文本框表单项、一个密码框表单项。文件名为 E:\s ,其内容如下:(其中的XXX代表二进制数据,如 01 02 03)
a
bb
XXX
ccc
客户端应该向 192.168.29.65 发送如下内容:
POST /upload_file/UploadFile HTTP/1.1
Accept: text/plain, */*
Accept-Language: zh-cn
Host: 192.168.29.65:80
Content-Type:multipart/form-data;boundary=---------------------------7d33a816d302b6
User-Agent: Mozilla/4.0 (compatible; OpenOffice.org)
Content-Length: 424
Connection: Keep-Alive
-----------------------------7d33a816d302b6
Content-Disposition: form-data; name="userfile1"; filename="E:\s"
Content-Type: application/octet-stream
a
bb
XXX
ccc
-----------------------------7d33a816d302b6
Content-Disposition: form-data; name="text1"
foo
-----------------------------7d33a816d302b6
Content-Disposition: form-data; name="password1"
bar
-----------------------------7d33a816d302b6--
此内容必须一字不差,包括最后的回车。
注意:Content-Length: 424 这里的424是红色内容的总长度(包括最后的回车)
注意这一行:
Content-Type: multipart/form-data; boundary=---------------------------7d33a816d302b6
根据 rfc1867, multipart/form-data是必须的.
---------------------------7d33a816d302b6 是分隔符,分隔多个文件、表单项。其中33a816d302b6 是即时生成的一个数字,用以确保整个分隔符不会在文件或表单项的内容中出现。前面的 ---------------------------7d 是 IE 特有的标志。 Mozila 为---------------------------71
用手工发送这个例子,在上述的 servlet 中检验通过。

(上面有一个回车)用户可以选择多个文件,填写表单其它项,点击“提交”按钮后就开始上传给http://192.168.29.65/upload_file/UploadFile 这是一个 servelet 程序
注意 enctype="multipart/form-data", method=post, type="file" 。根据 rfc1867, 这三个属性是必须的。multipart/form-data 是新增的编码类型,以提高二进制文件的传输效率。具体的解释请参阅 rfc1867

//

HEADER:

写道
......
Content-Type: multipart/form-data;

BODY:

Content-type: multipart/form-data, boundary=AaB03x--AaB03xcontent-disposition: form-data; name="field1"Joe Blow--AaB03xcontent-disposition: form-data; name="pics"Content-type: multipart/mixed, boundary=BbC04y--BbC04yContent-disposition: attachment; filename="file1.txt"

注释:

1 传文件的时候 使用的Media Type name: multipart , Media subtype name: form-data

2 boundary用来标识分割不同的field,其中文件是一个特殊的field

3 多个文件的时候得继续制定 Content-type: multipart/mixed ,同时定义新的 boundary

4 不同的field注意区分 Content-disposition 的值,是 form/data 还是 attachment

5 这里定义的是POST方式的上传,不针对PUT 。

2 如果需求非常确定每次请求只上传一个文件,那么我们可以不使用HTTP约定的这种方式,而改用一种更简单直接的方式:

- 在 HEDER 里的 POST 后的URL里携带普通参数 field

- 在 BODY里直接装在要上传的文件内容,抛弃任何格式等约束

- 服务端直接从BODY里读取流数据保存为文件,其他参数从URL里读取

这样以来HTTP报文就类似:

HEDER

写道
POST /HttpFileServer/upload?filename=nodexy.zip&fid=t01 HTTP/1.1
Host: www.yangzt.com:9190
Content-Length: xxxxx

BODY

写道
文件内容

注释:

1 这不是标准的文件上传方式,但仍然是标准的HTTP报文

2 这种私有约定的方式,需要服务端和客户端同时特异化处理

3 针对每次请求只传一个文件的需求,这样改良后就会比较简洁,至于效率上是否有明显差别还不得而知,未做测试对比

3 总结:

在HTTP协议这一层上做文件的上传下载,也是很常见的方式,尤其很多移动应用里会采用;因为对客户端来说打开一个URL来GET或POST数据,相比打开一个scocke连接来读取或写入数据要简单得多,实现也快捷高效。

HTTP协议上的上传下载,也可以轻松实现断点续传,和进度反馈等,主要依赖length和range两个值。所以作为标准考虑,一定要明确地设置header里的length属性 --- 如果不设置,对于一般浏览器来说无碍,仍然可以成功下载,但是对于诸如libcurl这样的类库来说则无法取到数据。

另外,TCP协议层上的文件上传下载,也是很常见的应用场景,改日再次涉及另作详谈。

/

在开发中,我们使用的比较多的HTTP请求方式基本上就是GET、POST。其中GET用于从服务器获取数据,POST主要用于向服务器提交一些表单数据,例如文件上传等。而我们在使用HTTP请求时中遇到的比较麻烦的事情就是构造文件上传的HTTP报文格式,这个格式虽说也比较简单,但也比较容易出错。今天我们就一起来学习HTTP POST的报文格式以及通过Java来模拟文件上传的请求。

首先我们来看一个POST的报文请求,然后我们再来详细的分析它。

POST报文格式

POST /api/feed/ HTTP/1.1
Accept-Encoding: gzip
Content-Length: 225873
Content-Type: multipart/form-data; boundary=OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp
Host: www.myhost.com
Connection: Keep-Alive--OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp
Content-Disposition: form-data; name="lng"
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit116.361545
--OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp
Content-Disposition: form-data; name="lat"
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit39.979006
--OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp
Content-Disposition: form-data; name="images"; filename="/storage/emulated/0/Camera/jdimage/1xh0e3yyfmpr2e35tdowbavrx.jpg"
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary这里是图片的二进制数据
--OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp--

这里我们提交的是经度、纬度和一张图片(图片数据比较长,而且比较杂乱,这里省略掉了)。

格式分析

请求头分析

我们先看 报文格式中的第一行:

POST /api/feed/ HTTP/1.1

这一行就说明了这个请求的请求方式,即为POST方式,要请求的子路径为/api/feed/,例如我们的服务器地址为www.myhost.com,然后我们的这个请求的完整路径就是 www.myhost.com/api/feed/,最后说明了HTTP协议的版本号为1.1。

Accept-Encoding: gzip
Content-Length: 225873
Content-Type: multipart/form-data; boundary=OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp
Host: www.myhost.com
Connection: Keep-Alive

这几个header的意思分别为服务器返回的数据需要使用gzip压缩、请求的内容长度为225873、内容的类型为"multipart/form-data"、请求参数分隔符(boundary)为OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp、请求的根域名为www.myhost.com、HTTP连接方式为持久连接( Keep-Alive)。

其中这里需要注意的一点是分隔符,即boundary。 boundary用于作为请求参数之间的界限标识,例如参数1和参数2之间需要有一个明确的界限,这样服务器才能正确的解析到参数1和参数2。但是分隔符并不仅仅是boundary,而是下面这样的格式:-- + boundary。例如这里的boundary为 OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp,那么参数分隔符则为:

--OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp

不管boundary本身有没有这个"--",这个"--"都是不能省略的。

我们知道HTTP协议采用“请求-应答”模式,当使用普通模式,即非KeepAlive模式时,每个请求/应答客户和服务器都要新建一个连接,完成之后立即断开连接(HTTP协议为无连接的协议);当使用Keep-Alive模式(又称持久连接、连接重用)时,Keep-Alive功能使客户端到服务器端的连接持续有效,当出现对服务器的后续请求时,Keep-Alive功能避免了建立或者重新建立连接。

如上图中,左边的是关闭Keep-Alive的情况,每次请求都需要建立连接,然后关闭连接;右边的则是Keep-Alive,在第一次建立请求之后保持连接,然后后续的就不需要每次都建立、关闭连接了, 启用Keep-Alive模式肯定更高效,性能更高,因为避免了建立/释放连接的开销 。

http 1.0中默认是关闭的,需要在http头加入"Connection: Keep-Alive",才能启用Keep-Alive;http 1.1中默认启用Keep-Alive,如果加入"Connection: close ",才关闭。目前大部分浏览器都是用http1.1协议,也就是说默认都会发起Keep-Alive的连接请求了,所以是否能完成一个完整的Keep- Alive连接就看服务器设置情况。

请求实体分析

请求实体其实就是HTTP POST请求的参数列表,每个参数以请求分隔符开始,即-- + boundary。例如下面这个参数。

--OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp
Content-Disposition: form-data; name="lng"
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit116.361545

上面第一行为--OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp,也就是--加上boundary内容, 最后加上一个换行 (这个换行不能省略),换行的字符串表示为"\r\n" 。第二行为Content-Disposition和参数名,这里的参数名为lng,即经度。 Content-Disposition就是当用户想把请求所得的内容存为一个文件的时候提供一个默认的文件名,这里我们不过多关注。第三行为 Content-Type,即 WEB 服务器告诉浏览器自己响应的对象的类型 ,还有指定字符编码为UTF-8。 第四行是 描述的是消息请求(request)和响应(response)所附带的实体对象(entity)的传输形式, 简单文本数据我们设置为8bit,文件参数我们设置为binary就行 。然后添加两个换行之后才是参数的具体内容。例如这里的参数内容为116.361545。

注意这里的每行之间都是使用“\r\n”来换行的,最后一行和参数内容之间是两个换行。文件参数也是一样的格式,只是文件参数的内容是字节流。

这里要注意一下,普通文本参数和文件参数有如下两个地方的不同,因为其内容本身的格式是不一样的。

普通参数:

Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

文件参数:

Content-Type: application/octet-stream
Content-Transfer-Encoding: binary

参数实体的最后一行是: --加上boundary加上--,最后换行,这里的 格式即为: --OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp--。

模拟文件上传请求

public static void uploadFile(String fileName) {try {
  // 换行符
  final String newLine = "\r\n";
  final String boundaryPrefix = "--";
  // 定义数据分隔线
  String BOUNDARY = "========7d4a6d158c9";
  // 服务器的域名
  URL url = new URL("www.myhost.com");
  HttpURLConnection conn = (HttpURLConnection) url.openConnection();
  // 设置为POST情
  conn.setRequestMethod("POST");
  // 发送POST请求必须设置如下两行
  conn.setDoOutput(true);
  conn.setDoInput(true);
  conn.setUseCaches(false);
  // 设置请求头参数
  conn.setRequestProperty("connection", "Keep-Alive");
  conn.setRequestProperty("Charsert", "UTF-8");
  conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
  OutputStream out = new DataOutputStream(conn.getOutputStream());
  // 上传文件
  File file = new File(fileName);
  StringBuilder sb = new StringBuilder();
  sb.append(boundaryPrefix);
  sb.append(BOUNDARY);
  sb.append(newLine);
  // 文件参数,photo参数名可以随意修改
  sb.append("Content-Disposition: form-data;name=\"photo\";filename=\"" + fileName
          + "\"" + newLine);
  sb.append("Content-Type:application/octet-stream");
  // 参数头设置完以后需要两个换行,然后才是参数内容
  sb.append(newLine);
  sb.append(newLine);
  // 将参数头的数据写入到输出流中
  out.write(sb.toString().getBytes());
  // 数据输入流,用于读取文件数据
  DataInputStream in = new DataInputStream(new FileInputStream(
          file));
  byte[] bufferOut = new byte[1024];
  int bytes = 0;
  // 每次读1KB数据,并且将文件数据写入到输出流中
  while ((bytes = in.read(bufferOut)) != -1) {
      out.write(bufferOut, 0, bytes);
  }
  // 最后添加换行
  out.write(newLine.getBytes());
  in.close();
  // 定义最后数据分隔线,即--加上BOUNDARY再加上--。
  byte[] end_data = (newLine + boundaryPrefix + BOUNDARY + boundaryPrefix + newLine)
          .getBytes();
  // 写上结尾标识
  out.write(end_data);
  out.flush();
  out.close();
  // 定义BufferedReader输入流来读取URL的响应
//  BufferedReader reader = new BufferedReader(new InputStreamReader(
//          conn.getInputStream()));
//  String line = null;
//  while ((line = reader.readLine()) != null) {//      System.out.println(line);
//  }} catch (Exception e) {
  System.out.println("发送POST请求出现异常!" + e);
  e.printStackTrace();}}

使用Apache Httpmime上传文件

/*** @param fileName 图片路径*/public static void uploadFileWithHttpMime(String fileName) {// 定义请求urlString uri = "www.myhost.com";// 实例化http客户端HttpClient httpClient = new DefaultHttpClient();// 实例化post提交方式HttpPost post = new HttpPost(uri);// 添加json参数try {
  // 实例化参数对象
  MultipartEntity params = new MultipartEntity();
  // 图片文本参数
  params.addPart("textParams", new StringBody(
          "{'user_name':'我的用户名','channel_name':'却道明','channel_address':'(123.4,30.6)'}",
          Charset.forName("UTF-8")));
  // 设置上传文件
  File file = new File(fileName);
  // 文件参数内容
  FileBody fileBody = new FileBody(file);
  // 添加文件参数
  params.addPart("photo", fileBody);
  params.addPart("photoName", new StringBody(file.getName()));
  // 将参数加入post请求体中
  post.setEntity(params);
  // 执行post请求并得到返回对象 [ 到这一步我们的请求就开始了 ]
  HttpResponse resp = httpClient.execute(post);
  // 解析返回请求结果
  HttpEntity entity = resp.getEntity();
  InputStream is = entity.getContent();
  BufferedReader reader = new BufferedReader(new InputStreamReader(is));
  StringBuffer buffer = new StringBuffer();
  String temp;
  while ((temp = reader.readLine()) != null) {
      buffer.append(temp);
  }
  System.out.println(buffer);} catch (UnsupportedEncodingException e) {
  e.printStackTrace();} catch (ClientProtocolException e) {
  e.printStackTrace();} catch (IOException e) {
  e.printStackTrace();} catch (IllegalStateException e) {
  e.printStackTrace();}}

http使用post上传文件时,请求头和主体信息总结相关推荐

  1. 阿里云OSS上传文件设置请求头

    之前写过一篇发送文件消息的,原生input上传文件(聊天发送文件消息),这次的需求就是更改上传地址,使用阿里云OSS上传. 如果想了解阿里云对象存储OSS是如何使用的,请看阿里云存储对象OSS使用讲解 ...

  2. Springboot上传文件时提示405

    问题描述:上传文件时请求不通,状态码返回405,如下图:  问题分析:405 Method Not Allowed,请求行中指定的请求方法不能被用于请求相应的资源.该响应必须返回一个Allow 头信息 ...

  3. 解决使用layui上传文件时提示“请求上传接口出现异常”

    在做网站的过程中,需要用户上传文件,接收文件的接口已经写好(经过测试确定可用) 现在需要在网页上提供一个文件上传的按钮.由于原生input type="file"组件太丑,考虑使用 ...

  4. 使用自开发的代理服务器解决 SAP UI5 FileUploader 上传文件时遇到的跨域访问错误试读版

    一套适合 SAP UI5 初学者循序渐进的学习教程 作者简介 Jerry Wang,2007 年从电子科技大学计算机专业硕士毕业后加入 SAP 成都研究院工作至今.Jerry 是 SAP 社区导师,S ...

  5. ajax文件上传重置,通过ajax上传文件时的ERR_CONNECTION_RESET

    当我使用jquery发送ajax请求上传文件时,我得到了#34; ERR_CONNECTION_RESET" 120秒后总是.所以,我决定在控制台中显示上传的进度,并且我惊讶地每30/40秒 ...

  6. 解决使用FireFox下Flash上传文件时SESSION丢失的问题(swfupload)

    解决使用FireFox下Flash上传文件时SESSION丢失的问题(swfupload) 这几天在项目中遇到的问题,稍微整理一下. HTML 表单是我们常用来进行浏览器与服务器数据交互的途径,除了传 ...

  7. 使用jquery.fileupload.js上传文件时添加进度条

    1.首先页面用来展示上传按钮 和 显示进度条的 <tr><td style="width:140px;text-align: right;padding-top: 13px ...

  8. smartupload 上传文件时 把页面编码改成gbk 解决乱码

    快来java1234 吧 smartupload 上传文件时,经常会发生因为把表单设置为 enctype="multipart/form-data"而出现的中文乱码问题,本人头疼好 ...

  9. php 上传文件名乱码,php上传文件时文件名乱码怎么办

    php上传文件时文件名乱码的解决方法:首先在脚本头部添加[header("Content-type: text/html; charset=utf-8");]:然后利用iconv( ...

  10. php自动分配,PHP上传文件时自动分配路径的方法_php技巧

    本文实例讲述了PHP上传文件时自动分配路径的方法.分享给大家供大家参考.具体分析如下: 网站上传文件时,如果是小的企业站,放在一个目录还没问题,当网站大了,上传的文件多了,我们就不能放在同一个目录了, ...

最新文章

  1. 【CSS3】自定义滚动条样式 -webkit-scrollbar
  2. 如何建立程序代码包的联接?
  3. 乔布斯和任正非相比,谁更厉害?
  4. CSS的历史与工作原理
  5. idea自动导入jar包的快捷键
  6. Java 集合体系详解——List体系有序集合
  7. 《零基础》MySQL 查询数据(十二)
  8. 使用jsoncpp解析json文件
  9. 从一个小场景学会使用 apply方法
  10. java求sobel算子代码_sobel算子原理与实现
  11. hutool中的threadutil_Hutool
  12. Android改包1
  13. 2020时尚COSMO美容大奖“破圈直播间”完美收官!打造美妆直播全新形式!
  14. 【易通慧谷】供应链金融六大模式解析
  15. js格式化显示json对象
  16. Linux下Tab键补全,报No space left on device错误
  17. elementui[el-table]表格全选操作以及翻页选中取消相关效果
  18. 海康威视摄像头用yolo检测行人的一些问题
  19. 英语日常用语900句(5)
  20. Android apk瘦身之使用TinyPng压缩图片

热门文章

  1. unity json解析IPA后续
  2. Repeater 中TextBox 触发TextChanged事件
  3. setTimeout里如果有$(this),$(this)指的是谁?
  4. POJ3185(简单BFS,主要做测试使用)
  5. 对上拉下拉电阻的作用作个总结(想了解的过来看看)(转载)
  6. ellen 纽奥良大学演讲
  7. ASP.NET Web 服务、企业服务和 .NET Remoting 的性能
  8. 手机号正则表达 php,php 手机号码正则表达试程序代码_PHP教程
  9. 曝光原理_泰国精戈咖啡效果反馈 作用原理曝光
  10. 计算机科学家和心理学家合作,生物智能与人工智能之间的合作