成了!阿里云oss自动同步制作-后台php

阅读次数: 2,086

  • A+
所属分类:C语言 PHP 建站

前几天用PHP做好了一个自动同步的功能

最近使用时发现,如果自动同步的文件过大时,脚本执行时间会很长,time_limit = 0 丫没有卵用。导致apache服务器直接报错。

没办法现在考虑用php的爸爸来做这个功能了。

2019-12-03先做准备

https://help.aliyun.com/document_detail/32134.html?spm=5176.8466049.0.0.204b1450IYQ0Lm

根据这篇文章先把功能安装好,再开始做自动同步吧。

过程中核心命令

gcc -Wall -O -g -I /usr/local/include/oss_c_sdk -I /usr/include/apr-1 -c main.c -o main.o
gcc main.o -o main -lpthread -L/usr/local/lib -loss_c_sdk -lcurl -lmxml -L/usr/local/apr/lib -lapr-1 -laprutil-1

安装流程

1.安装 CMake和第三方库 (centos)

安装CMake

yum install cmake

安装第三方库

sudo yum install curl-devel apr-devel apr-util-devel  mxml mxml-devel 

这里等下会出现错误(因为mxml版本过高)

2.安装SDK

如果 curl、apr、apr-util 和 mxml 第三方库安装在默认路径下时,安装方式如下:

cmake .
make
make install

如果 curl、apr、apr-util 和 mxml 第三方库不是安装在默认路径下,安装 SDK时,需要指定其安装路径,安装方式如下:

cmake -f CMakeLists.txt
// 编译类型为Release。常用的编译类型为:Debug、Release、RelWithDebInfo和MinSizeRel,默认使用Debug。
-DCMAKE_BUILD_TYPE=Release
// 自定义安装目录。
-DCMAKE_INSTALL_PREFIX=/usr/local/
// 指定curl、apr、apr-util和xml第三方库头文件和库文件的所在目录。
-DCURL_INCLUDE_DIR=/usr/include/curl
-DCURL_LIBRARY=/usr/lib64/libcurl.so
-DAPR_INCLUDE_DIR=/usr/include/apr-1
-DAPR_LIBRARY=/usr/lib64/libapr-1.so
-DAPR_UTIL_INCLUDE_DIR=/usr/include/apr-1
-DAPR_UTIL_LIBRARY=/usr/lib64/libaprutil-1.so
-DMINIXML_INCLUDE_DIR=/usr/include
-DMINIXML_LIBRARY=/usr/lib64/libmxml.so
// 编译时,如果报`Could not find apr-config/apr-1-config`,原因是在默认路径里面找不到apr-1-config文件,请添加该选项。
-DAPR_CONFIG_BIN=/path/to/bin/apr-1-config
// 如果报:Could not find apu-config/apu-1-config,请添加该选项。
-DAPU_CONFIG_BIN=/path/to/bin/apu-1-config

其他错误请看文章尾部

3.使用SDK

C/C++程序,从源代码到执行,需要经过编译、链接、运行三个步骤。OSS C SDK应用亦是如此,下面分别对这三个步骤详细说明。

编译

编译,将源代码编译成目标文件(*.obj),主要过程是预编译、语法检查、生成目标文件。预编译会对源代码中引用的头文件进行查找。语法检查即符号检查,对于函数,检查引用和原型是否匹配。编译时,有头文件即可编译通过,不需要查找库,所以也不需要指定库的位置。

GCC/G++搜索头文件的顺序如下:

编译源文件时指定的搜索路径,GCC/G++通过-I指定;

环境变量C_INCLUDE_PATH/CPLUS_INCLUDE_PATH指定的搜索路径

( 默认为空。 )

GCC/G++默认的头文件搜索路径;

包括`/usr/include`,`/usr/local/include` 和 `GCC/G++的头文件目录`。GCC/G\++的头文件目录,不同Linux系统下稍有不同。

GCC的头文件目录,通过如下命令查看

`gcc -print-prog-name=cc1` -v

G\+\+的头文件目录,通过如下命令查看

`g++ -print-prog-name=cc1` -v 

OSS C SDK应用依赖的库,不指定安装目录,使用默认安装目录时,有以下两种安装方式:

  • 使用apt-get、yum、rpm命令安装;
  • 使用源代码安装且不指定安装路径。

使用默认安装目录时,对于不同的Linux,依赖库的头文件位置稍有不同。头文件路径是否在GCC/G++搜索路径中,如下表:

Linuxcurlapr/aprutilmxmlsdk
Aliyun/Centos不在,默认安装路径 /usr/include/apr-1不在,默认安装路径 /usr/local/include/oss_c_sdk
Debian不在,默认安装路径 /usr/include/apr-1.0不在,默认安装路径 /usr/local/include/oss_c_sdk
Redhat不在,默认安装路径 /usr/local/apr/include/apr-1不在,默认安装路径 /usr/local/include/oss_c_sdk
SuSE不在,默认安装路径 /usr/include/apr-1不在,默认安装路径 /usr/local/include/oss_c_sdk
Ubuntu不在,默认安装路径 /usr/local/include/oss_c_sdk


编译示例程序main.c,Ubuntu系统执行以下命令:

gcc -Wall -O -g -I. -I /usr/local/include/oss_c_sdk -c main.c -o main.o

Aliyun/Centos系统执行以下命令:

gcc -Wall -O -g -I /usr/local/include/oss_c_sdk -I /usr/include/apr-1 -c main.c -o main.o

注意:

  • 编译、链接、运行小节中,第三方库和OSS C SDK库都采用不指定路径的方式安装,即使用默认安装目录;指定依赖库的安装路径,其编译、链接、运行的使用方法在 指定安装路径 小节中介绍。

链接

链接,把目标程序和依赖库链接成一个整体,生成可执行文件。对于静态库,链接时把整个库写入可执行文件;运行时不需要再指定,但是可执行程序会变大。动态库链接时,可执行程序中只记录库的信息(位置、大小、版本等)和调用的函数信息(名称、偏移等)。动态库是程序共享的,可执行程序也不会膨胀。

对于使用OSS C SDK的应用,推荐使用动态库。本文中和官网提供的示例,都使用动态库。GCC/G++对动态库的搜索路径如下:

  • 链接目标文件时指定的搜索路径,GCC/G++通过-L指定;
  • 环境变量LD_LIBRARY_PATH指定的搜索路径; 
    默认是空的。
  • 配置文件/etc/ld.so.conf中指定的搜索路径; 
    /etc/ld.so.conf内容是ld.so.conf.d/*.conf,即包括/etc/ld.so.conf.d/*.conf配置的路径。 
    可以使用命令ldconfig -v查看所有可以使用的动态库;使用如下命令查看动态库的搜索路径
ldconfig -v | grep -v ^$'\t'
  • 系统默认的动态库搜索路径/lib、/usr/lib或/lib64、/usr/lib64;
  • GCC/G++的默认的搜索路径。 
    可以通过命令gcc -print-search-dirs查看。

上面五部分组成了依赖库的搜索路径。如果依赖库不在上述路径中,链接时需要使用-L指定。
对于不同的Linux系统,OSS C SDK应用依赖的库位置稍有不同,它们的路径是否在GCC/G++搜索路径中,如下表:

Linuxcurlapr/aprutilmxmlsdk
Aliyun/Centos不在,默认安装路径/usr/local/apr/lib不在,默认安装路径/usr/local/lib
Debian不在,默认安装路径/usr/local/apr/lib不在,默认安装路径/usr/local/lib
Redhat不在,默认安装路径/usr/local/apr/lib不在,默认安装路径/usr/local/lib
SuSE
Ubuntu

链接示例main.o与依赖库 ,Ubuntu/SuSE执行以下命令:

gcc main.o -o main -lpthread -loss_c_sdk -lcurl -lmxml -lapr-1 -laprutil-1

Aliyun/Centos/Debian/Redhat执行以下命令:

gcc main.o -o main -lpthread -L/usr/local/lib -loss_c_sdk -lcurl -lmxml -L/usr/local/apr/lib -lapr-1 -laprutil-1

运行

运行,将可执行程序加载到内存并执行。执行时需要引用动态库。
运行时动态库搜索顺序如下:

  • 环境变量LD_LIBRARY_PATH指定的搜索路径; 
    默认为空。
  • 配置文件/etc/ld.so.conf中指定的搜索路径; 
    /etc/ld.so.conf内容是ld.so.conf.d/*.conf,即包括/etc/ld.so.conf.d/*.conf配置的路径。 
    可以使用命令ldconfig -v查看所有可以使用的动态库;使用如下命令查看动态库的搜索路径:
ldconfig -v | grep -v ^$'\t'
  • 系统默认的动态库搜索路径/lib、/usr/lib或/lib64、/usr/lib64。

如果链接时用-L指定了动态库的路径,且不在上述三类路径中,运行时需要使用LD_LIBRARY_PATH指定。如果运行
示例main时,报如下错误:

./main: error while loading shared libraries: liboss_c_sdk.so.3.0.0: cannot open shared object file: No such file or directory

说明运行时找不到动态库liboss_c_sdk。请使用LD_LIBRARY_PATH指定,执行如下命令:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib

提示:

  • 示例代码中的OSS_ENDPOINT、ACCESS_KEY_ID、ACCESS_KEY_SECRET、BUCKET_NAME请更换成有效值。

指定安装路径

编译OSS C SDK应用的设备上,如果没有ROOT权限,安装第三方库和OSS C SDK时,需要指定安装目录。除非必要,不推荐安装依赖库时指定安装路径。

比如安装第三方库和OSS C SDK时,指定安装目录都是/home/your/oss/csdk,编译示例程序使用如下命令:

gcc -Wall -O -g -I. -I /home/your/oss/csdk/include -I /home/your/oss/csdk/include/oss_c_sdk -I /home/your/oss/csdk/include/curl -I /home/your/oss/csdk/include/apr-1 -c main.c -o main.o

链接示例程序使用如下命令:

gcc main.o -o main -lpthread -L/home/your/oss/csdk/lib -loss_c_sdk -lcurl -lmxml -lapr-1 -laprutil-1

执行示例程序使用如下命令:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/your/oss/csdk/lib
./main

三个命令

Linux使用依赖库,下面三个命令可能会用到,详细功能和参数请使用man cmd查看。

ldconfig
动态库管理命令
ldd
显示可执行模块的依赖库
nm
显示可执行模块中符号的信息

目前根据上边的流程 oss_sdk已经安装成功

开始 编写shell

记录节点12月5号

oss_service.sh

#!/bin/bash
EXEC_PATH=/usr/local/oss
EXEC=oss
DAEMON=$EXEC_PATH/$EXEC
PID_FILE=/var/run/$EXEC.pid

test -f /etc/rc.d/init.d/functions && . /etc/rc.d/init.d/functions

if [ ! -f $DAEMON ] ; then
       echo "ERROR: $DAEMON not found"
       exit 1
else
        chmod +x $DAEMON
fi
add(){
        echo "oss add"
        $DAEMON --add
        echo -e "                 [ \033[36mOK\033[0m ]"
}

del(){
        echo "oss del"
        echo -e "                      [ \033[31mFailed\033[0m ]"
}
echo
case "$1" in
    add)
        add
        ;;
    del)
        del
        ;;
    *)
        echo "Usage: service $EXEC {add|del}"
        exit 1
esac
echo
exit $?

oss.sh

#!/bin/sh

add(){
        echo "i am oss_add function"
        echo "第一个参数 $1"
        echo "第二个参数 $2"
        echo "-- \$@ 演示 ---"
        for i in "$@"; do
                echo $i
        done
}

del(){
        echo "i am oss_del function"
}
showhelp(){
        echo "i am help"
}

while [ $1 ]; do
        case $1 in
                '-h' | '--help' | '?' )
                        showhelp
                        exit
                        ;;
                '--add' | '-add' )
                        add $2 $3
                        break;
                        ;;
                '--del' | '-del' )
                        del $2
                        break;
                        ;;
                *)
                        showhelp
                        exit
                        ;;
        esac
        shift
done
ln -sf /usr/local/oss /bin/oss  //类似加入 pathinfo

以上是笔记,以下是成功后的详细记录

整体思路

后台PHP 异步请求上传功能并传送一个回调地址,服务器端上传完成后再请求回调地址,后台php再改变MySQL is_oss(是否上传云端完成)状态改为1。

步骤一 制作一个公共命令,类似能在windows里的cmd窗口里直接敲出的命令。(原理该命令在 系统或用户path里即可 各种系统原理一样)

1.创建一个目录

mkdir /usr/local/oss

一般默认linux安装成功的软件都在这个位置

2.创建执行命令文件

cd /usr/local/oss
vim oss

3.oss的代码是

#!/bin/sh

add(){
        echo "i am oss_add function"
        echo "第一个参数 $1"
        echo "第二个参数 $2"
        echo "-- \$@ 演示 ---"
        for i in "$@"; do
                echo $i
        done
#### centos7.6+ 的会报错 加上这句 再执行就不会
        export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
        /home/tool/oss/shell/oss $1
        echo "上传完成执行回调"
        curl -i $2

}

del(){
        echo "i am oss_del function"
}
showhelp(){
        echo "i am help"
}

while [ $1 ]; do
        case $1 in
                '-h' | '--help' | '?' )
                        showhelp
                        exit
                        ;;
                '--add' | '-add' )
                        add $2 $3
                        break;
                        ;;
                '--del' | '-del' )
                        del $2
                        break;
                        ;;
                *)
                        showhelp
                        exit
                        ;;
        esac
        shift
done

当前的版本比较简陋

4.放进 /bin下 让全局都可以使用到

ln -sf /usr/local/oss/oss /bin/oss

5.测试

成了!阿里云oss自动同步制作-后台php

说明成功了。

步骤二 制作上传到云端的程序

我这里直接在 SDK里边修改了

思路:

1.传递一个文件夹的绝对路径

2.遍历所有文件,遍历过程中直接上传

3.上传上去的新文件名称根据配置文件来替换(如 /data/www/www.shikexu.com/video/2019/12/06/d3sse12 源文件 新文件 video/2019/12/06/d3sse12/xxx.jpg 等等)

4.上传失败时写入日志(单个文件)

源码开始:

文件一 (配置文件 site.conf)

mkdir /usr/local/oss/config
vim /usr/local/oss/config/site.conf

site.conf 内容

site_path = /data/www/www.shikexu.com/

文件二(主文件 oss.c)

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include "aos_log.h"
#include "aos_util.h"
#include "aos_string.h"
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include "aos_status.h"
#include "oss_auth.h"
#include "oss_util.h"
#include "oss_api.h"

#define MAX_PATH_LEN (256)
#define CONFIG_FILE "/usr/local/oss/config/site.conf"

const char OSS_ENDPOINT[] = "######";
const char ACCESS_KEY_ID[] = "######";
const char ACCESS_KEY_SECRET[] = "######";
const char BUCKET_NAME[] = "######";
const char OBJECT_NAME[] = "c_test.jpg";

char *site_path;
char *api_url;

void init_sample_request_options(oss_request_options_t *options, int is_cname);

void put_object_from_buffer();
void put_object_from_file();
void get_object_to_buffer();
void get_object_to_file();
void delete_object();

/* 读取配置文件 start */
char* Get_Config(char *Config_name)
{
  char readbuf[512] = {0};
  char findbuf[100] = {0};
  char *retbuf;
  retbuf = (char *)malloc(100);
  strcpy(findbuf,Config_name);
  int line = 0;
  FILE *fp = fopen(CONFIG_FILE,"r");
  if(fp == NULL)
  {
    perror("fopen");
    return NULL;
  }
  while(fgets(readbuf,sizeof(readbuf),fp)) //逐行循环读取文件,直到文件结束
  {
    line++;
    if(!strncmp(readbuf,"#",1) || !strncmp(readbuf,"\n",1)) //忽略注释(#)和空行
      continue;
    if(strstr(readbuf,findbuf))     //查找配置文件名
    {
      char *p=strchr(readbuf,'=');  //确定“=”位置
      do
      {
        p += 1;
      }
      while(*p == ' ');
      sprintf(retbuf,"%s",p);
      fclose(fp);
      return retbuf;
    }
  }
  return NULL;
}

/* 读取配置文件 end */


/* 中文名称的文件 start */
/* 中文名称的文件 end */

/* 字符串的替换 start */
char *strrpc(char *str,char *oldstr,char *newstr){
	char bstr[strlen(str)];//转换缓冲区
	memset(bstr,0,sizeof(bstr));
	int i;
	for(i=0;i<strlen(str);i++){
		if(!strncmp(str+i,oldstr,strlen(oldstr))){
			strcat(bstr,newstr);
			i += strlen(oldstr) - 1;
		}else{
			strncat(bstr,str+i,1);
		}
	}
	strcpy(str,bstr);
	return str;
}
/* 字符串的替换 end */
         

static void trave_dir(char* path){
        DIR *d = NULL;
	char s_file[100];//源文件
	char t_file[100];//临时的
	char *n_file;//新的文件名
	char s_path[100];//配置文件要存放的字符串
        struct dirent *dp = NULL; /* readdir函数的返回值就存放在这个结构体中 */
        struct stat st;
        char p[MAX_PATH_LEN] = {0};

        if(stat(path,&st) < 0 || !S_ISDIR(st.st_mode)){
                printf("invalid path: %s\n",path);
                return;
        }

        if(!(d = opendir(path))){
                printf("opendir[%s] error: %m\n",path);
                return;
        }

        while((dp = readdir(d)) != NULL){
                /* 把当前目录. 上级目录 ..及隐藏文件都去掉 避免死循环 */
                if((!strncmp(dp->d_name,".",1)) || (!strncmp(dp->d_name,"..",2)))
continue;
                snprintf(p ,sizeof(p) - 1,"%s/%s",path,dp->d_name);
                stat(p,&st);
                if(!S_ISDIR(st.st_mode)){
                        printf("%s%s\n",path,dp->d_name);
			printf("我是文件的记录\n");
			/* 是文件而不是目录时 开始上传 start */
			// /www/wwwroot/www.shikexu.com/video/m3u8/2019/12/05/4a44ssea  下的所有文件上传到
			// video/m3u8/2019/12/05/4a44ssea/feng.jpg  每个独立的文件都需要去掉前缀
			// 整理出来要上传原始文件路径 和上传后的文件名称
			sprintf(s_file,"%s",p);
			printf("源文件是%s\n",s_file);		
			strcpy(t_file,s_file);
			sprintf(s_path,"%s",site_path);
			printf("站点的路径是:%s\n",s_path);
			s_path[strlen(s_path)-1] = 0;
			/* 打印出配置文件的原型 start */
			//int i;
			//for(i=0;i<strlen(s_path);i++){
			//	printf("%c\n",s_path[i]);
			//}	

			/* 打印出配置文件的原型 end */
			n_file = strrpc(t_file,s_path,"");//替换求出上传上去的新的文件名
			
			printf("新文件是%s\n",n_file);	
			//printf("站点路径是%s\n",site_path);
			//printf("替换后源文件是%s\n",s_file);		
			//printf("临时的路径是%s\n",t_file);
			/* 开始上传 start */
			put_object_from_file(s_file,n_file);	
			/* 开始上传 end */
			/* 是文件而不是目录时 开始上传 end */
                }else{
			printf("我是目录的记录\n");
                        printf("%s/\n",dp->d_name);
                        trave_dir(p);
                }
        }
        closedir(d);

        return;
}


int main(int argc, char *argv[])
{

	/* 获取配置 start */
	site_path = Get_Config("site_path");
	printf("站点路径是%s\n",site_path);
//	free(site_path); 释放防止内存泄露
	/* 获取配置 end */

    apr_file_t *output = NULL;
    aos_pool_t *pool = NULL;
    apr_status_t ret;
    
    // initialize http io system, call it olny once
    if (aos_http_io_initialize(NULL, 0) != AOSE_OK) {
        exit(1);
    }
    
    aos_pool_create(&pool, NULL);

    // open log file
    ret = apr_file_open(&output, "oss-c-sdk.log", APR_FOPEN_CREATE | APR_FOPEN_WRITE | APR_FOPEN_APPEND, APR_OS_DEFAULT, pool);
    if (APR_SUCCESS != ret) {
        exit(1);
    }
 
    // set log file
    aos_log_set_output(output);
    // set log level
    aos_log_set_level(AOS_LOG_INFO);

    aos_info_log("start");


/* 开始根据目录来遍历文件 通过循环的方式来上传文件 start */
	char *path = NULL;
        if(argc !=2){
                printf("Usage: %s [dir]\n",argv[0]);
                printf("use DEFAULT option: %s .\n",argv[0]);
                printf("------------------------------\n");
                path = "./";
        }else{
                path = argv[1];
        }

        trave_dir(path);

	

/* 开始根据目录来遍历文件 通过循环的方式来上传文件 end */




    // run samples
    // put_object_from_buffer();
//    char file_name = "我是中文.txt";
 //    put_object_from_file(file_name);
    //get_object_to_buffer();
    //get_object_to_file();
//    delete_object();

    // close log file
    apr_file_close(output); 

    aos_pool_destroy(pool);

    // deinitialize http io system, call it olny once
    aos_http_io_deinitialize();

    return 0;
}

void init_sample_request_options(oss_request_options_t *options, int is_cname)
{
    options->config = oss_config_create(options->pool);
    aos_str_set(&options->config->endpoint, OSS_ENDPOINT);
    aos_str_set(&options->config->access_key_id, ACCESS_KEY_ID);
    aos_str_set(&options->config->access_key_secret, ACCESS_KEY_SECRET);
    options->config->is_cname = is_cname;

    options->ctl = aos_http_controller_create(options->pool, 0);
}

void put_object_from_buffer()
{
    aos_pool_t *p = NULL;
    aos_string_t bucket;
    aos_string_t object;
    int is_cname = 0;
    aos_table_t *headers = NULL;
    aos_table_t *resp_headers = NULL;
    oss_request_options_t *options = NULL;
    aos_list_t buffer;
    aos_buf_t *content = NULL;
    char *str = "test oss c sdk";
    aos_status_t *s = NULL;

    aos_pool_create(&p, NULL);
    options = oss_request_options_create(p);
    init_sample_request_options(options, is_cname);
    headers = aos_table_make(p, 1);
    apr_table_set(headers, "x-oss-meta-author", "oss");
    aos_str_set(&bucket, BUCKET_NAME);
    aos_str_set(&object, OBJECT_NAME);

    aos_list_init(&buffer);
    content = aos_buf_pack(options->pool, str, strlen(str));
    aos_list_add_tail(&content->node, &buffer);

    s = oss_put_object_from_buffer(options, &bucket, &object, 
                   &buffer, headers, &resp_headers);

    if (aos_status_is_ok(s)) {
        printf("put object from buffer succeeded\n");
    } else {
        printf("put object from buffer failed\n");      
    }    

    aos_pool_destroy(p);
}

void put_object_from_file(char *file_name,char *new_name)
{
//	char file_name[100] = "我是中文.txt";
	/* 转换中文的文件名 start */

	/* 转换中文的文件名 end */


    aos_pool_t *p = NULL;
    aos_string_t bucket;
    aos_string_t object;
    int is_cname = 0;
    aos_table_t *headers = NULL;
    aos_table_t *resp_headers = NULL;
    oss_request_options_t *options = NULL;
 //   char *filename = "1.txt";
    aos_status_t *s = NULL;
    aos_string_t file;

    aos_pool_create(&p, NULL);
    options = oss_request_options_create(p);
    init_sample_request_options(options, is_cname);
    headers = aos_table_make(options->pool, 1);
    //apr_table_set(headers, OSS_CONTENT_TYPE, "image/jpeg");

    aos_str_set(&bucket, BUCKET_NAME);
    aos_str_set(&object, new_name);
    aos_str_set(&file, file_name);

    s = oss_put_object_from_file(options, &bucket, &object, &file, 
                                 headers, &resp_headers);

    if (aos_status_is_ok(s)) {
        printf("put object from file succeeded\n");
    } else {
        printf("put object from file failed, code:%d, error_code:%s, error_msg:%s, request_id:%s\n",
            s->code, s->error_code, s->error_msg, s->req_id);
    }

    aos_pool_destroy(p);
}

void get_object_to_buffer()
{
    aos_pool_t *p = NULL;
    aos_string_t bucket;
    aos_string_t object;
    int is_cname = 0;
    oss_request_options_t *options = NULL;
    aos_table_t *headers = NULL;
    aos_table_t *params = NULL;
    aos_table_t *resp_headers = NULL;
    aos_status_t *s = NULL;
    aos_list_t buffer;
    aos_buf_t *content = NULL;
    char *buf = NULL;
    int64_t len = 0;
    int64_t size = 0;
    int64_t pos = 0;

    aos_pool_create(&p, NULL);
    options = oss_request_options_create(p);
    init_sample_request_options(options, is_cname);
    aos_str_set(&bucket, BUCKET_NAME);
    aos_str_set(&object, OBJECT_NAME);
    aos_list_init(&buffer);

    s = oss_get_object_to_buffer(options, &bucket, &object, 
                                 headers, params, &buffer, &resp_headers);

    if (aos_status_is_ok(s)) {
        printf("get object to buffer succeeded\n");
    }
    else {
        printf("get object to buffer failed\n");  
    }

    //get buffer len
    aos_list_for_each_entry(aos_buf_t, content, &buffer, node) {
        len += aos_buf_size(content);
    }

    buf = aos_pcalloc(p, (apr_size_t)(len + 1));
    buf[len] = '\0';

    //copy buffer content to memory
    aos_list_for_each_entry(aos_buf_t, content, &buffer, node) {
        size = aos_buf_size(content);
        memcpy(buf + pos, content->pos, (size_t)size);
        pos += size;
    }

    aos_pool_destroy(p);
}

void get_object_to_file()
{
    aos_pool_t *p = NULL;
    aos_string_t bucket;
    char *download_filename = "SouthIsland_NewZealand_New.jpg";
    aos_string_t object;
    int is_cname = 0;
    oss_request_options_t *options = NULL;
    aos_table_t *headers = NULL;
    aos_table_t *params = NULL;
    aos_table_t *resp_headers = NULL;
    aos_status_t *s = NULL;
    aos_string_t file;

    aos_pool_create(&p, NULL);
    options = oss_request_options_create(p);
    init_sample_request_options(options, is_cname);
    aos_str_set(&bucket, BUCKET_NAME);
    aos_str_set(&object, OBJECT_NAME);
    headers = aos_table_make(p, 0);
    aos_str_set(&file, download_filename);

    s = oss_get_object_to_file(options, &bucket, &object, headers, 
                               params, &file, &resp_headers);

    if (aos_status_is_ok(s)) {
        printf("get object to local file succeeded\n");
    } else {
        printf("get object to local file failed\n");
    }

    aos_pool_destroy(p);
}

void delete_object()
{
    aos_pool_t *p = NULL;
    aos_string_t bucket;
    aos_string_t object;
    int is_cname = 0;
    oss_request_options_t *options = NULL;
    aos_table_t *resp_headers = NULL;
    aos_status_t *s = NULL;

    aos_pool_create(&p, NULL);
    options = oss_request_options_create(p);
    init_sample_request_options(options, is_cname);
    aos_str_set(&bucket, BUCKET_NAME);
    aos_str_set(&object, OBJECT_NAME);

    s = oss_delete_object(options, &bucket, &object, &resp_headers);

    if (aos_status_is_ok(s)) {
        printf("delete object succeed\n");
    } else {
        printf("delete object failed\n");
    }

    aos_pool_destroy(p);
}

其中 请将这四个替换成你自己的

OSS_ENDPOINT

ACCESS_KEY_ID

ACCESS_KEY_SECRET

BUCKET_NAME

替换后开始编译和运行测试

特别注意 ./oss /data/www/www.shikexu.com/video 这个后边的参数最后 不要带 /

看结果:

成了!阿里云oss自动同步制作-后台php

成功。

总结:

过程中遇到很多问题

问题1:(安装问题)安装OSS SDK时会出现 libmxml-dev 版本过高,然后具体会报什么错误我忘了。

出现原因 centos下 使用 yum自动安装导致的

sudo yum install curl-devel apr-devel apr-util-devel  mxml mxml-devel

解决办法

用稍低的版本

rpm -qa | grep libxml //查看安装的包包
yum -y remove libxml*  //删除刚才安装的 3.0
rpm -ql libxml2-2.9.1-6.el7_2.3.x86_64  //查看安装软件的路径

下载 这个 2.9版本的 然后

tar zxf mxml-2.9.tar.gz
./configure && make && sudo make install
cmake -DMINIXML_LIBRARY=/usr/local/lib/libmxml.a .
make

问题2 根据绝对路径获取 目录下的所有文件

解决办法

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>

#define MAX_PATH_LEN (256)

static void trave_dir(char* path){
        DIR *d = NULL;
        struct dirent *dp = NULL; /* readdir函数的返回值就存放在这个结构体中 */
        struct stat st;
        char p[MAX_PATH_LEN] = {0};

        if(stat(path,&st) < 0 || !S_ISDIR(st.st_mode)){
                printf("invalid path: %s\n",path);
                return;
        }

        if(!(d = opendir(path))){
                printf("opendir[%s] error: %m\n",path);
                return;
        }

        while((dp = readdir(d)) != NULL){
                /* 把当前目录. 上级目录 ..及隐藏文件都去掉 避免死循环 */
                if((!strncmp(dp->d_name,".",1)) || (!strncmp(dp->d_name,"..",2)))
continue;
                snprintf(p ,sizeof(p) - 1,"%s/%s",path,dp->d_name);
                stat(p,&st);
                if(!S_ISDIR(st.st_mode)){
//                      printf("%s%s\n",path,dp->d_name);
                        printf("%s\n",p);
                }else{
                        printf("%s/\n",dp->d_name);
                        trave_dir(p);
                }
        }
        closedir(d);

        return;
}

int main(int argc,char **argv){
        char *path = NULL;
        if(argc !=2){
                printf("Usage: %s [dir]\n",argv[0]);
                printf("use DEFAULT option: %s .\n",argv[0]);
                printf("------------------------------\n");
                path = "./";
        }else{
                path = argv[1];
        }

        trave_dir(path);

        return 0;
}

问题3 如何获取 根据配置文件来赋值

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

#define FILENAME "./site.conf"

char* Get_Config(char *Config_name)
{
  char readbuf[512] = {0};
  char findbuf[50] = {0}; 
  char *retbuf;
  retbuf = (char *)malloc(50);
  strcpy(findbuf,Config_name);
  int line = 0;
  FILE *fp = fopen(FILENAME,"r");
  if(fp == NULL)
  {
    perror("fopen");
    return NULL;
  }
  while(fgets(readbuf,sizeof(readbuf),fp)) //逐行循环读取文件,直到文件结束
  {
    line++;
    if(!strncmp(readbuf,"#",1) || !strncmp(readbuf,"\n",1)) //忽略注释(#)和空行
      continue;
    if(strstr(readbuf,findbuf))     //查找配置文件名
    {
      char *p=strchr(readbuf,'=');  //确定“=”位置
      do
      {
        p += 1;
      }
      while(*p == ' ');
      sprintf(retbuf,"%s",p);
      fclose(fp);
      return retbuf;
    }
  }
  return NULL;
}

char* del_space(char *str){
	int i = -1,j = strlen(str),cur=0;
	char *fp = NULL;
	char *fp_temp = NULL;
	if(str == NULL){
		return "error";
	}
	while(str[++i] == ' '){
	}
	while(str[--j] == ' '){
	}
	for(;i<=j;i++,++cur){
		str[cur] = str[i];
	}
	str[cur] = '\0';
	fp = fp_temp = str;//记录字符串
	while(*str){
		if(*str != ' '){
		*fp_temp = *str;	
		fp_temp++;
		}else{
			if(*(fp_temp -1) != ' '){
				*fp_temp = *str;
				fp_temp++;
			}
		}
		str++;
	}
	*fp_temp = '\0';
	return fp;
}

char *strrpc(char *str,char *oldstr,char *newstr){
    char bstr[strlen(str)];//转换缓冲区
    memset(bstr,0,sizeof(bstr));
        int i;
    for(i = 0;i < strlen(str);i++){
        if(!strncmp(str+i,oldstr,strlen(oldstr))){//查找目标字符串
            strcat(bstr,newstr);
            i += strlen(oldstr) - 1;
        }else{
                strncat(bstr,str + i,1);//保存一字节进缓冲区
            }
    }

    strcpy(str,bstr);
    return str;
}

void main1(){
	char str[] = "      sdfdsf  sdfds sss sdfsd  ";
	char *p = del_space(str);
	printf("%s",p);
}

int main(int argc, const char *argv[])
{
	char *test = "/www/wwwroot/video.shikexu.com/";
	char *site_path;

  	site_path = Get_Config("site_path");
	printf("site_path:%s",site_path);
	char s_path[100];
	
	sprintf(s_path,"%s",site_path);
//	strcpy(temp,site_path);
	
	s_path[strlen(s_path)-1] = 0;
	printf("s_path:%s\n",s_path);

  	free(site_path); //防止内存泄漏
	printf("test:%s\n",test);
	printf("test的长度为%d\n",strlen(test));
	printf("s_path的长度为%d\n",strlen(s_path));
	printf("对比结果%d\n",strcmp(s_path,test));
	char str[] = "/www/wwwroot/video.shikexu.com/video/m3u8/2019/11/29/d23";
	strrpc(str,s_path,"");
	printf("last:%s\n",str);
	return 0;
}

问题4 php脚本执行时间过长

解决办法异步执行 exec

$cmd = 'oss -add '.$task_path' "'.$api_url.'" >/dev/null &';
exec($cmd);

输出到 /dev/null 再加 & 后台执行。


至此结束,我现在还不会C,还需要继续学习。

转载请声明--原文地址

  • 我的微信
  • 这是我的微信扫一扫
  • weinxin
  • 我的微信公众号
  • 我的微信公众号扫一扫
  • weinxin

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: