Linux下cURL使用教程之六:curl基本使用之HTTP文件上传

有些时候,不只需要提交表单,还需要上传附件。本篇针对上传文件,对上篇curl提交表单进行补充。
注:本篇只针对HTTP上传文件部分。

PHP程序

同前,所有服务端代码通过php实现。

  • file.php,显示文件上传表单:
    <html>
    <head>
    <title>
    PHP FileUpload Demo for curl basic usage By Adeploy
    </title>
    </head>
    <body>
    This is a PHP File Upload Demo.<br />
    Select a file and Submit.<br /><br />
    <form action="upload_file.php" method="post"
    enctype="multipart/form-data">
    <label for="file">Filename:</label>
    <input type="file" name="file" id="file" />
    <br /><br />
    <input type="submit" name="submit" value="Submit" />
    </form>
    <br /><br /><br />
    <a href="http://www.adeploy.com" target="_blank">Adeploy's Blog</a>
    </body>
    </html>
  • upload_file.php,处理上传的文件。
    上传文件后,文件先缓存在临时目录中,脚本结束时临时文件被删除。upload_file.php只是简单输出上传文件的信息,而不做实际场景中将临时文件保存至永久目录等进一步处理。但此差异对我们进行curl实验没有任何影响。

    <html>
    <head>
    <title>
    PHP FileUpload Demo for curl basic usage By Adeploy
    </title>
    </head>
    <body>
    This is a File Upload Process Demo.<br />
    It only shows the information of the file you uploaded.<br />
    The file you uploaded remains temporary,<br />
    and is deleted when this script is finished.<br /><br />
    <?php
    if ($_FILES["file"]["error"] > 0)
    {
    echo "Error: " . $_FILES["file"]["error"] . "<br />";
    }
    else
    {
    echo "Upload: " . $_FILES["file"]["name"] . "<br />";
    echo "Type: " . $_FILES["file"]["type"] . "<br />";
    echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
    echo "Stored in: " . $_FILES["file"]["tmp_name"];
    }
    ?>
    <br><br><br>
    <a href="http://www.adeploy.com" target="_blank">Adeploy's Blog</a>
    </body>
    </html>
  • put.php,处理通过HTTP PUT方法上传的文件。
    同上,为了安全只输出上传文件信息,不做实际转存处理。

    <html>
    <head>
    <title>
    PHP Form Demo for curl basic usage By Adeploy
    </title>
    </head>
    <body>
    This is a PHP PUT Demo.<br>
    It reads the file you upload using PUT,<br>
    and prints the content out.<br><br>
    <?php
    /* PUT data comes in on the stdin stream */
    $putdata = fopen("php://input", "r");

    /* Read the data 1 KB at a time
    and print the content out */
    echo "The contents of the file you upload:<br><br>\n";
    while ($data = fread($putdata, 1024))
    echo $data;
    echo "<br>";
    /* Close the streams */
    fclose($putdata);
    ?>
    <br /><br /><br />
    <a href="http://www.adeploy.com" target="_blank">Adeploy's Blog</a>
    </body>
    </html>

主要参数

-F/–form

-F/--form <name=content>
使用Content-Type multi‐part/form-data的方式提交数据,可用于上传二进制文件。

  1. @的使用
    一般使用-F file=@filename的形式,其中file为文件表单的name,filename为文件名。@后面的文件作为文件上传处理。

  2. <的使用
    对于<后的文件,curl会读取其内容,而不会作为文件上传。类似-d选项中@的作用。

    curl -F name=<foobar.txt -Fage=100 http://127.0.0.1/welcome.php
    foobar.txt内容为Adeploy,则此命令与以下命令等价:
    curl -F name=Adeploy -Fage=100 http://127.0.0.1/welcome.php
    而-F @foobar.txt表示将foobar.txt作为文件上传。

  3. -F不进行url编码
    -F与-d类似,都是不对数据进行urlencode编码,而且-F不能与-d或–data-urlencode共用。
    因此如果上传文件的同时还需要提交其他需要urlencode编码的字段(如中文用户名),就会出现问题。
    除手动编码外,实用的解决办法是自己编写urlencode函数(网上可以找到Linux脚本实现的urlencode函数或C语言版本、Perl版本、Python),调用即可。

  4. 使用”type=”指定Content-Type
    curl -F "web=@index.html;type=text/html" url.com
    将index.html以text/html的Content-Type上传。

  5. 使用”filename=”修改上传文件的名字
    curl -F "file=@localfile;filename=nameinpost" url.com
    上传localfile并修改文件名字为nameinpost。

–form-string

--form-string <name=string>
基本同-F,但是此参数后面跟”@”、”<”、”;type=”时,不做特殊含义解析。

-T/–upload-file

-T/--upload-file <file>
使用HTTP的PUT方法上传文件,需要目标URL支持HTTP的PUT方法。
可以与-d、–data-urlencode、-F同时使用。

参数使用实例

-F文件上传

打开file.php选择文件后submit,Developer Tools抓包截图如下:
Developer Tools file上传
注意此时的Content-Type字段是multipart/form-data,主要用于上传文件,具体可参考RFC1867
分析file.php的源代码可知,表单中file类型的input元素name=file,所以命令如下:

curl -s -o file.html -F file=@a.txt http://127.0.0.1/upload_file.php

-T文件上传

没有找到正确的PUT表单,因此无法使用Developer Tools跟踪实际提交过程。
命令:

curl -s -o put.html -T a.txt http://127.0.0.1/put.php

总结

本篇主要为使用curl上传文件的操作方法。