利用PUT方式上传文件的方法研究

虽然没有POST方法使用广泛,但是PUT方法却是向服务器上传文件最有效率的方法。POST上传文件时,我们通常需要将所有的信息组合成 multipart 传送过去,然后服务器再解码这些信息,解码过程则必不可少的会消耗内存和CPU资源,这种现象在上传大文件时尤其明显。而PUT方法则允许你通过与服务器建立的socket链接传递文件的内容,而不附带其他的信息。

最近一个项目上需要利用这种方式来进行文件的上传,下面介绍一下在 Apache + PHP 的环境下如何进行PUT方式的文件上传。

Apache 有一个模块 mod_actions,先看看官方的说明:

This module has two directives. The Action directive lets you run CGI scripts whenever a file of a certain MIME content type is requested. The Script directive lets you run CGI scripts whenever a particular method is used in a request. This makes it much easier to execute scripts that process files.

也就是说,这个模块可以指定对于特定 MIME 类型的文件处理,或者对于特定脚本的请求进行指定的处理。我用到的就是 Script 这个选项。

在Apache 配置文件的 Directory 中指定

Script PUT /receive.php

这个含义就是,对于所有对服务器的PUT请求,都交给根目录下的 receive.php 去处理,当然我们也可以选择 perl 或者其他的CGI脚本来进行处理。

接下来就是这个 receive.php 脚本的编写了,他的主要任务就是将请求的文件写到指定的位置

<?php
/**
* Process The PUT File, receive and move a file to corresponsed location
* Created by shiqiang<cocowool@gmail.com> at 2010-05-24
*
**/

class Receive {
    var $default_log_file = "logs/error.log";
    var $default_server_info = "logs/server.log";
    var $default_header_info = "logs/header.log";
    var $default_prefix = "/data1/vhosts";    //Default project location prefix;
    var $default_module = "test.cn";
    var $max_filesize = 2048000;
    var $request_uri;

    function Receive(){
        $this->request_uri = $_SERVER['REQUEST_URI'];
    }
    function saveFile(){
        //receive data and save
        $putdata = fopen("php://input", "r");

        $path = $this->getPath($this->request_uri);
        $fp = fopen($path, 'w');
        while($data = fread($putdata, 1024) ){
            fwrite($fp, $data);
        }

        fclose($fp);
        fclose($putdata);

        //Log The filesize check and limit check
        if( filesize($path) != $_SERVER['CONTENT_LENGTH'] ){
            $this->errorLog( "[warn] " . date("Y-m-d H:i:s")  . " The file's ($path) size dosen't match Server Filesize = " . filesize($path) . "; Put Filesize = " . $_SERVER['CONTENT_LENGTH']. "\r\n" );
            header('HTTP/1.1 526 Receive Data Error');
        }

        if( filesize($path) > $this->max_filesize ){
            $this->errorLog( "[warn] " . date("Y-m-d H:i:s")  . " The file's ($path) size exceed the system limit");
        }
    }

    //Log Error Info
    function errorLog( $info ){
        $f = fopen($this->default_log_file, 'a+');
        fwrite($f, $info);
        flcose($f);
    }

    function serverLog(){
        $f = fopen($this->default_server_info, 'w');
        $info = $_SERVER;
        $str = "The Last Request Server Info:\r\n";
        foreach ($info as $key => $value){
            $str .= "$key = $value\r\n";
        }
        $str .= $this->getPath($this->request_uri) . "\r\n";
        $str .= "PHP_UPLOADED_FILE_NAME=" . $PHP_UPLOADED_FILE_NAME . "\r\n";
        fwrite($f , $str);
        fclose($f);
    }

    //Log the Request Header info
    function headerLog(){
        $f = fopen($this->default_header_info, 'w');
        $info = get_headers();
        $str = "The Last Request header Info:\r\n";
        foreach ($info as $key => $value){
            $str .= "$key = $value\r\n";
        }
        fwrite($f , $str);
        fclose($f);
    }

    //get the path where the file should be
    function getPath($uri){
        $module = $this->defalt_module;    //Default storage module

        $referer = $this->request_uri;
        preg_match('/(?<=\/)(.*?)(?=\/)/s', $referer, $match);

        if( !empty($match) && !empty($match[0]) ){
            $module = $match[0];
        }

        $path = $this->default_prefix;
        $path .= '/' . $module . '/htdocs';
        $fullpath = substr($uri, strlen($match[0]) + 1, strlen($uri) );

        $arr = explode('/', ltrim($fullpath, '/'));
        foreach($arr as $v){
            if( !strstr($v, '.') ){
                $path .= '/' . $v;
                //exec("echo $path >> dir.txt");
                if( !is_dir($path) ){
                    //For php > 5.0
                    //mkdir($path, "0766", true);
                    mkdir($path, 0766);
                }
            }else{
                $path .= '/' . $v;
            }
        }

        return $path;
    }

}

$instance = new Receive();
$instance->serverLog();
//$instance->headerLog();
$instance->saveFile();

?>

这个脚本,使用PHP手册中的接收PUT方式的方法,详细的使用,GOOGLE的时候,并没有找到很多,所以可能对于错误情况,考虑的也不是很全面,如果有使用过这个方法的欢迎和我讨论。

Technorati 标签: PHP,PUT,Script

参考资料:
1、PUT Upload
2、RFC 2616

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/465484.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2个字符串相等 swift_Swift快速入门(一)之 Swift基础语法

Swift快速入门&#xff08;一&#xff09;之 Swift基础语法近期重新学习了一遍Swift语言&#xff0c;主要以《Swift编程权威指南&#xff08;第2版&#xff09;》为教程&#xff0c;学习过程中结合比对Java语言特性将学习心得作为三篇笔记&#xff1a;Swift基础语法&#xff0c…

python-day3

1.内存 sublime中程序运行一次后&#xff0c;变量并不保存在内存中&#xff0c;和maya中不一样。转载于:https://www.cnblogs.com/moyanljx/p/9319988.html

nginx+mysql+php+cacti+rrdtool全方位架构急速版

时间调整&#xff1a; /usr/sbin/ntpdate stdtime.sinica.edu.twcentos5.2 系统测试OK 新机全配置步骤及方法&#xff1a; 1、给系统刷新下yum 主件加速yum安装的速度&#xff1b; yum -y install yum-fastestmirror.noarch 引用 warning: rpmts_HdrFromFdno: Header V3 DSA si…

bootstrap switch只出现一个对号_python:34.第一个只出现一次的字符位置

题目描述在一个字符串(0<字符串长度<10000&#xff0c;全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1&#xff08;需要区分大小写&#xff09;.解析暴力解法&#xff0c;时间复杂度是 。# -*- coding:utf-8 -*- class Solution:def Fi…

Java基础(三)对象与类

1.类的概念&#xff1a;类是构造对象的模板或蓝图。由类构造对象的过程称为创建类的实例。 2.封装的概念&#xff1a;封装&#xff08;有时称为数据隐藏&#xff09;是与对象有关的一个重要概念。对象中的数据称为实例域&#xff0c;操纵数据的过程称为方法。对于每个特定的类实…

mac系统如何进入系统偏好设置_MacOS Big Sur 系统偏好设置无法解锁Bug解决

前不久&#xff0c;MacOS推送正式版Big Sur&#xff0c;我满怀期待的更新。更新的过程很平缓&#xff0c;一切都很顺利。但在使用时&#xff0c;出现了一个问题&#xff0c;系统偏好设置的锁无法解除&#xff0c;导致有些软件需要权限&#xff0c;却不能正常允许通过&#xff0…

English trip -- VC(情景课)2 D Reading

Xu言&#xff1a; 业精于勤&#xff0c;荒于嬉&#xff1b;行成于思&#xff0c;毁于随 Before you read 阅读准备 Talk about the picture&#xff0c; what do you see&#xff1f;看图说话&#xff0c;你看到了什么&#xff1f; Listen and read 听并读 Sue, Have fun at sc…

VLAN访问控制列表(VACL)的配置方法

VLAN访问控制列表(VACL)的配置方法同普通的访问控制列表不同,VACL是用在VLAN内对数据进行过滤的,而前者是用在第三层接口对出入的数据包进行过滤,例如:在同一个VLAN内部,我们可能不允许其他主机对另一台主机进行访问,此时我们可以使用VLAN来实现,其配置方法如下:1.创建VACL(是以…

事务嵌套问题_注意Spring事务这一点,避免出现大事务

背景本篇文章主要分享压测的(高并发)时候发现的一些问题。之前的两篇文章已经讲述了在高并发的情况下&#xff0c;消息队列和数据库连接池的一些总结和优化&#xff0c;有兴趣的可以在我的公众号中去翻阅。废话不多说&#xff0c;进入正题。事务&#xff0c;想必各位CRUD之王对…

js规范

一个js文件中&#xff0c;包含多个函数&#xff0c;应该只有一个调用&#xff0c;例如: var fun function(x) {if (x < 1) {return x;} else {return -x;} }function ensure(condition, message) {if (!condition) {console.log(message)} }function testFun() {ensure(fun…

原来嵌套个网页的技术是这样的

一开始被其他技术说的似乎很难实现一样&#xff0c;以前自己学过点开发的技术&#xff0c;不过都是皮毛&#xff0c;本想走开发的&#xff0c;没走成&#xff0c;呵呵&#xff0c;还是走到了自己的本专业。 页面一、 <html> <head> <meta http-equiv"Conte…

多布局怎么搭建_怎么制作网页?网页制作基本步骤

怎么制作网页?网页制作基本步骤&#xff0c;互联网时代&#xff0c;各行各业的企业为了适应时代的发展&#xff0c;纷纷从线下转移至线上来拓展自己的业务。若想让更多人了解自己的企业&#xff0c;拥有一个专属网站至关重要。网站不仅可以详细介绍企业信息&#xff0c;更重要…

git github

今日内容&#xff1a;git 1. 版本管理工具 - git - svn https://git-scm.com/downloads 2. 大表哥创业故事&#xff1a;北京热 a. 初次创建版本 git init git config --global user.email "youexample.com" git config --global user.name "Your Name"…

系统的常用安装方法

原装系统安装1、 开机看屏幕提示进入BIOS设置引导顺序&#xff0c;First Boot设置为CD-ROM。一般是按Delete键进入&#xff0c;或者是F12直接进入引导菜单选择CD-ROM&#xff08;现代新的主板会有引导菜单&#xff09; 2、 设置光驱引导&#xff08;主板不同可能设置有所不同&a…

C++重载运算符

其实在C中&#xff0c;运算符也是一种函数&#xff0c;有自己的类型&#xff0c;有自己的参数&#xff0c;有自己的返回值。 下面就是重载的方法&#xff1a; struct vec {int x;int y; }; vec operator(const vec &a,const vec &b) //括号里面的是参数 {vec temp;temp…

能运行shell吗_terminal, shell, bash, zsh

##秋天的第一杯奶茶梗?Terminal: shell运行在里面。A terminal refers to a wrapper program that runs a shell.Shell:The shell is the program that actually processes commands and returns outputs. Most shells also manage foreground and background processes, comm…

ROJECT SERVER如何与OUTLOOK集成使用

最近一直挺忙&#xff0c;换了个工作环境&#xff0c;接手一个project server的管理。公司项目挺多&#xff0c;企业资源、wbs 、视图&#xff0c;管理类别很多要定义。项目成员使用习惯是个问题&#xff0c;就整理了project协作使用说明。 登陆WPA站点<?xml:namespace pr…

python制作点亮图片_MicroPython拼插编程实例:点亮心形8x8点阵

一、什么是TPYBoard开发板TPYBoard是以遵照MIT许可的MicroPython为基础的一款MicroPython开发板&#xff0c;它基于STM32F405单片机&#xff0c;通过USB接口进行数据传输。该开发板内置4个LED灯、一个加速传感器&#xff0c;可在3V-10V之间的电压正常工作。TPYBoard开发板让用户…

OSPF的虚链路配置

OSPF的虚链路配置<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />OSPF多区要求普通区域必须和骨干区域&#xff08;area 0&#xff09;相连&#xff0c;如果一个区域不能和骨干区域直接相连&#xff0c;可以使用虚链路把该区域逻…

webmvcconfigurer配置跨域_为什么加了 Spring Security 会导致 Spring Boot 跨域失效呢?...

点击上方 IT牧场 &#xff0c;选择 置顶或者星标技术干货每日送达作者&#xff1a;欧阳我去链接&#xff1a;https://segmentfault.com/a/1190000019485883作为一个后端开发&#xff0c;我们经常遇到的一个问题就是需要配置 CORS&#xff0c;好让我们的前端能够访问到我们的 AP…