实现对文件以及文件夹的压缩解压缩.
zip_unzip.h
#ifndef ZIP_UNZIP_H
#define ZIP_UNZIP_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "zlib.h"
#include "contrib/minizip/zip.h"
#include "contrib/minizip/unzip.h"
using namespace std::filesystem;
class zip_unzip
{
public:
zip_unzip();
//add file
void add_file_to_zip_arrary(std::string file);
void add_directory_to_zip_arrary(std::string directory);
void recursive_file_to_zip_arrary(std::string directory);
int get_file_count();
//zip
void run_zip_arrary(const char * dest_zip_path);
void run_file_zip(std::string file, const char * dest_zip_path);
void run_dest_zip(std::string dest_floder_path, const char * dest_zip_path);
//unzip
int run_unzip(std::string source_zip_path, std::string dest_floder_path);
private:
std::vector> vec_file_tuple; //存放文件路径以及对应的父目录
std::string error_info;
static std::string parent_folder_path;
};
#endif // ZIP_UNZIP_H
zip_unzip.cpp
#include "zip_unzip.h"
#define FOPEN_FUNC(filename, mode) fopen64(filename, mode)
#define FTELLO_FUNC(stream) ftello64(stream)
#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin)
#define WRITEBUFFERSIZE (16384)
#define MAXFILENAME (256)
int filetime(
const char *f, /* name of file to get info on */
tm_zip *tmzip, /* return value: access, modific. and creation times */
uLong *dt ) /* dostime */
{
(void)dt;
int ret=0;
struct stat s; /* results of stat() */
struct tm* filedate;
time_t tm_t=0;
if (strcmp(f,"-")!=0)
{
char name[MAXFILENAME+1];
size_t len = strlen(f);
if (len > MAXFILENAME)
len = MAXFILENAME;
strncpy(name, f,MAXFILENAME-1);
/* strncpy doesnt append the trailing NULL, of the string is too long. */
name[ MAXFILENAME ] = '\0';
if (name[len - 1] == '/')
name[len - 1] = '\0';
/* not all systems allow stat'ing a file with / appended */
if (stat(name,&s)==0)
{
tm_t = s.st_mtime;
ret = 1;
}
}
filedate = localtime(&tm_t);
tmzip->tm_sec = filedate->tm_sec;
tmzip->tm_min = filedate->tm_min;
tmzip->tm_hour = filedate->tm_hour;
tmzip->tm_mday = filedate->tm_mday;
tmzip->tm_mon = filedate->tm_mon ;
tmzip->tm_year = filedate->tm_year;
return ret;
}
int isLargeFile(const char* filename)
{
int largeFile = 0;
ZPOS64_T pos = 0;
FILE* pFile = FOPEN_FUNC(filename, "rb");
if(pFile != NULL)
{
FSEEKO_FUNC(pFile, 0, SEEK_END);
pos = (ZPOS64_T)FTELLO_FUNC(pFile);
printf("File : %s is %lld bytes\n", filename, pos);
if(pos >= 0xffffffff)
largeFile = 1;
fclose(pFile);
}
return largeFile;
}
int getFileCrc(const char* filenameinzip,void*buf,unsigned long size_buf,unsigned long* result_crc)
{
unsigned long calculate_crc=0;
int err=ZIP_OK;
FILE * fin = FOPEN_FUNC(filenameinzip,"rb");
unsigned long size_read = 0;
unsigned long total_read = 0;
if (fin==NULL)
{
err = ZIP_ERRNO;
}
if (err == ZIP_OK)
do
{
err = ZIP_OK;
size_read = fread(buf,1,size_buf,fin);
if (size_read < size_buf)
if (feof(fin)==0)
{
printf("error in reading %s\n",filenameinzip);
err = ZIP_ERRNO;
}
if (size_read>0)
calculate_crc = crc32_z(calculate_crc,(Bytef *)buf,size_read);
total_read += size_read;
} while ((err == ZIP_OK) && (size_read>0));
if (fin)
fclose(fin);
*result_crc=calculate_crc;
printf("file %s crc %lx\n", filenameinzip, calculate_crc);
return err;
}
void exclude_path(std::string &path, std::string &include_path){
//去除文件路径
const char *tmpptr;
const char *lastslash = 0;
if(include_path.empty()){
for( tmpptr = path.c_str(); *tmpptr; tmpptr++)
{
if( *tmpptr == '\\' || *tmpptr == '/')
{
lastslash = tmpptr;
}
}
if( lastslash != NULL )
{
path = lastslash+1; // base filename follows last slash.
}
}
else{
path = path.substr(include_path.length());
for(tmpptr = path.c_str();*tmpptr;tmpptr++){
if( *tmpptr != '\\' && *tmpptr != '/')
{
lastslash = tmpptr;
break;
}
}
if( lastslash != NULL )
{
path = lastslash; // base filename follows last slash.
}
}
}
static void change_file_date(
const char *filename,
uLong dosdate,
tm_unz tmu_date)
{
#ifdef _WIN32
HANDLE hFile;
FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite;
hFile = CreateFileA(filename,GENERIC_READ | GENERIC_WRITE,
0,NULL,OPEN_EXISTING,0,NULL);
GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite);
DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal);
LocalFileTimeToFileTime(&ftLocal,&ftm);
SetFileTime(hFile,&ftm,&ftLastAcc,&ftm);
CloseHandle(hFile);
#else
#if defined(unix) || defined(__APPLE__)
(void)dosdate;
struct utimbuf ut;
struct tm newdate;
newdate.tm_sec = tmu_date.tm_sec;
newdate.tm_min=tmu_date.tm_min;
newdate.tm_hour=tmu_date.tm_hour;
newdate.tm_mday=tmu_date.tm_mday;
newdate.tm_mon=tmu_date.tm_mon;
if (tmu_date.tm_year > 1900)
newdate.tm_year=tmu_date.tm_year - 1900;
else
newdate.tm_year=tmu_date.tm_year ;
newdate.tm_isdst=-1;
ut.actime=ut.modtime=mktime(&newdate);
utime(filename,&ut);
#endif
#endif
}
static int mymkdir(
const char* dirname)
{
int ret=0;
#ifdef _WIN32
ret = _mkdir(dirname);
#elif unix
ret = mkdir (dirname,0775);
#elif __APPLE__
ret = mkdir (dirname,0775);
#endif
return ret;
}
static int makedir (
const char *newdir)
{
char *buffer ;
char *p;
size_t len = strlen(newdir);
if (len == 0)
return 0;
buffer = (char*)malloc(len+1);
if (buffer==NULL)
{
printf("Error allocating memory\n");
return UNZ_INTERNALERROR;
}
strcpy(buffer,newdir);
if (buffer[len-1] == '/') {
buffer[len-1] = '\0';
}
if (mymkdir(buffer) == 0)
{
free(buffer);
return 1;
}
p = buffer+1;
while (1)
{
char hold;
while(*p && *p != '\\' && *p != '/')
p++;
hold = *p;
*p = 0;
if ((mymkdir(buffer) == -1) && (errno == ENOENT))
{
printf("couldn't create directory %s\n",buffer);
free(buffer);
return 0;
}
if (hold == 0)
break;
*p++ = hold;
}
free(buffer);
return 1;
}
static int do_extract_currentfile(
unzFile uf,
const int* popt_extract_without_path,
int* popt_overwrite,
const char* password)
{
char filename_inzip[256];
char* filename_withoutpath;
char* p;
int err=UNZ_OK;
FILE *fout=NULL;
void* buf;
uInt size_buf;
unz_file_info64 file_info;
err = unzGetCurrentFileInfo64(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
if (err!=UNZ_OK)
{
printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);
return err;
}
size_buf = WRITEBUFFERSIZE;
buf = (void*)malloc(size_buf);
if (buf==NULL)
{
printf("Error allocating memory\n");
return UNZ_INTERNALERROR;
}
p = filename_withoutpath = filename_inzip;
while ((*p) != '\0')
{
if (((*p)=='/') || ((*p)=='\\'))
filename_withoutpath = p+1;
p++;
}
if ((*filename_withoutpath)=='\0')
{
if ((*popt_extract_without_path)==0)
{
printf("creating directory: %s\n",filename_inzip);
mymkdir(filename_inzip);
}
}
else
{
const char* write_filename;
int skip=0;
if ((*popt_extract_without_path)==0)
write_filename = filename_inzip;
else
write_filename = filename_withoutpath;
err = unzOpenCurrentFilePassword(uf,password);
if (err!=UNZ_OK)
{
printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err);
}
if (((*popt_overwrite)==0) && (err==UNZ_OK))
{
char rep=0;
FILE* ftestexist;
ftestexist = FOPEN_FUNC(write_filename,"rb");
if (ftestexist!=NULL)
{
fclose(ftestexist);
}
*popt_overwrite=1;
}
if ((skip==0) && (err==UNZ_OK))
{
fout=FOPEN_FUNC(write_filename,"wb");
/* some zipfile don't contain directory alone before file */
if ((fout==NULL) && ((*popt_extract_without_path)==0) &&
(filename_withoutpath!=(char*)filename_inzip))
{
char c=*(filename_withoutpath-1);
*(filename_withoutpath-1)='\0';
makedir(write_filename);
*(filename_withoutpath-1)=c;
fout=FOPEN_FUNC(write_filename,"wb");
}
if (fout==NULL)
{
printf("error opening %s\n",write_filename);
}
}
if (fout!=NULL)
{
printf(" extracting: %s\n",write_filename);
do
{
err = unzReadCurrentFile(uf,buf,size_buf);
if (err<0)
{
printf("error %d with zipfile in unzReadCurrentFile\n",err);
break;
}
if (err>0)
if (fwrite(buf,(unsigned)err,1,fout)!=1)
{
printf("error in writing extracted file\n");
err=UNZ_ERRNO;
break;
}
}
while (err>0);
if (fout)
fclose(fout);
if (err==0)
change_file_date(write_filename,file_info.dosDate,
file_info.tmu_date);
}
if (err==UNZ_OK)
{
err = unzCloseCurrentFile (uf);
if (err!=UNZ_OK)
{
printf("error %d with zipfile in unzCloseCurrentFile\n",err);
}
}
else
unzCloseCurrentFile(uf); /* don't lose the error */
}
free(buf);
return err;
}
int do_extract(
unzFile uf,
int opt_extract_without_path,
int opt_overwrite,
const char* password)
{
uLong i;
unz_global_info64 gi;
int err;
err = unzGetGlobalInfo64(uf,&gi);
if (err!=UNZ_OK)
printf("error %d with zipfile in unzGetGlobalInfo \n",err);
for (i=0;i(file_tuple);
cur_parent_folder_path = std::get<1>(file_tuple);
zip_fileinfo zi={};
zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0;
zi.dosDate = 0;
zi.internal_fa = 0;
zi.external_fa = 0;
filetime(cur_file_path.c_str(),&zi.tmz_date,&zi.dosDate);
int zip64 = 0;
zip64 = isLargeFile(cur_file_path.c_str());
/* The path name saved, should not include a leading slash. */
/*存入zip的文件路进需要去掉/或者\前缀*/
file_in_zip_path={};
file_in_zip_path = cur_file_path;
exclude_path(file_in_zip_path, cur_parent_folder_path);
auto error = zipOpenNewFileInZip3_64(create_zip_file,file_in_zip_path.c_str(),&zi,
NULL,0,NULL,0,NULL /* comment*/,
Z_DEFLATED,
Z_DEFAULT_COMPRESSION,0,
/* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */
-MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
nullptr,0, zip64);
if(error != ZIP_OK){
error_info = {};
error_info = error_info + "zipOpenNewFileInZip failed, error: " + " errno"+std::to_string(error);
return ;
}
FILE * file_pointer = nullptr;
file_pointer = fopen(cur_file_path.c_str(),"rb");
if(file_pointer==nullptr){
error_info = {};
error_info = error_info + "fopen failed, zip file: " + cur_file_path + " errno"+std::to_string(errno);
return ;
}
char bytes_buf[100*1024]={};
int bytes_num = 0;
while(!feof(file_pointer)){
bytes_num = fread(bytes_buf, 1, sizeof(bytes_buf),file_pointer);
zipWriteInFileInZip(create_zip_file, bytes_buf,bytes_num);
if(ferror(file_pointer))
break;
memset(bytes_buf,0,sizeof(bytes_buf));
}
fclose(file_pointer);
zipCloseFileInZip(create_zip_file);
}
zipClose(create_zip_file,nullptr);
}
void zip_unzip::run_file_zip(std::string file, const char * dest_zip_path){
add_file_to_zip_arrary(file);
run_zip_arrary(dest_zip_path);
}
void zip_unzip::run_dest_zip(std::string dest_floder_path, const char * dest_zip_path){
add_directory_to_zip_arrary(dest_floder_path);
run_zip_arrary(dest_zip_path);
}
int zip_unzip::run_unzip(std::string source_zip_path, std::string dest_floder_path){
const char *filename_to_extract=NULL;
const char *password=NULL;
char filename_try[MAXFILENAME+16] = "";
int i;
int ret_value=0;
int opt_do_list=0;
int opt_do_extract=1;
int opt_do_extract_withoutpath=0;
int opt_overwrite=0;
int opt_extractdir=0;
const char *dirname=NULL;
unzFile uf=NULL;
strncpy(filename_try, source_zip_path.c_str(), MAXFILENAME-1);
/* strncpy doesnt append the trailing NULL, of the string is too long. */
filename_try[ MAXFILENAME ] = '\0';
uf = unzOpen64(source_zip_path.c_str());
if (uf==nullptr)
{
strcat(filename_try,".zip");
uf = unzOpen64(filename_try);
}
if (uf == nullptr){
error_info = {};
error_info = error_info + "unzOpen64 failed, error: " + " errno"+std::to_string(errno);
ret_value = 1;
return ret_value;
}
//判断目录是否存在
path dest_path(dest_floder_path);
if(!exists(dest_floder_path)){
//创建目录
if(!makedir(dest_floder_path.c_str())){
error_info = {};
error_info = error_info + "chdir failed, error: " + dest_floder_path + " errno"+std::to_string(errno);
ret_value = 2;
return ret_value;
}
}
if(chdir(dest_floder_path.c_str())){
error_info = {};
error_info = error_info + "chdir failed, error: " + dest_floder_path + " errno"+std::to_string(errno);
ret_value = 3;
return ret_value;
}
ret_value = do_extract(uf,opt_do_extract_withoutpath,opt_overwrite,password);
unzClose(uf);
return ret_value;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(ziplib LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
include_directories(ziplib/src)
include_directories(/software/sharedlibrary/zlib/zlib-1.2.12)
find_library(SRC_ZLIB_A libz.a /software/sharedlibrary/zlib/zlib-1.2.12 NO_DEFAULT_PATH)
link_libraries(${SRC_ZLIB_A})
add_library(ziplib STATIC
src/zip_unzip.cpp
src/zip_unzip.h
src/zip.o
src/unzip.o
src/ioapi.o
src/crc32.h
src/crc32.o
)
target_link_libraries(ziplib -STATIC_LIBRARY_FLAGS
stdc++fs
)
其中zip.o unzip.o,ioapi.o,crc32.h crc32.o为zlib库编译时生成的文件
uos@uos-PC:/software/sharedlibrary/zlib/zlib-1.2.12/contrib/minizip$ tree
.
├── configure.ac
├── crypt.h
├── ioapi.c
├── ioapi.h
├── ioapi.o
├── iowin32.c
├── iowin32.h
├── Makefile
├── Makefile.am
├── make_vms.com
├── miniunz
├── miniunz.c
├── miniunzip.1
├── miniunz.o
├── minizip
├── minizip.1
├── MiniZip64_Changes.txt
├── MiniZip64_info.txt
├── minizip.c
├── minizip.o
├── minizip.pc.in
├── mztools.c
├── mztools.h
├── unzip.c
├── unzip.h
├── unzip.o
├── zip.c
├── zip.h
└── zip.o
编译前需要下载编译安装zlib库,下载链接:
http://www.zlib.net/zlib-1.2.12.tar.gz
uos@uos-PC:/software/sharedlibrary/zlib/zlib-1.2.12$ ./configure --prefix=/software/sharedlibrary/zlib-static --static
Checking for gcc...
Building static library libz.a version 1.2.12 with gcc.
Checking for size_t... Yes.
Checking for off64_t... Yes.
Checking for fseeko... Yes.
Checking for strerror... Yes.
Checking for unistd.h... Yes.
Checking for stdarg.h... Yes.
Checking whether to use vs[n]printf() or s[n]printf()... using vs[n]printf().
Checking for vsnprintf() in stdio.h... Yes.
Checking for return value of vsnprintf()... Yes.
Checking for attribute(visibility) support... Yes.
uos@uos-PC:/software/sharedlibrary/zlib/zlib-1.2.12$ make
gcc -O3 -D_LARGEFILE64_SOURCE=1 -DHAVE_HIDDEN -I. -c -o example.o test/example.c
gcc -O3 -D_LARGEFILE64_SOURCE=1 -DHAVE_HIDDEN -c -o adler32.o adler32.c
gcc -O3 -D_LARGEFILE64_SOURCE=1 -DHAVE_HIDDEN -c -o crc32.o crc32.c
gcc -O3 -D_LARGEFILE64_SOURCE=1 -DHAVE_HIDDEN -c -o deflate.o deflate.c
gcc -O3 -D_LARGEFILE64_SOURCE=1 -DHAVE_HIDDEN -c -o infback.o infback.c
gcc -O3 -D_LARGEFILE64_SOURCE=1 -DHAVE_HIDDEN -c -o inffast.o inffast.c
gcc -O3 -D_LARGEFILE64_SOURCE=1 -DHAVE_HIDDEN -c -o inflate.o inflate.c
gcc -O3 -D_LARGEFILE64_SOURCE=1 -DHAVE_HIDDEN -c -o inftrees.o inftrees.c
gcc -O3 -D_LARGEFILE64_SOURCE=1 -DHAVE_HIDDEN -c -o trees.o trees.c
gcc -O3 -D_LARGEFILE64_SOURCE=1 -DHAVE_HIDDEN -c -o zutil.o zutil.c
gcc -O3 -D_LARGEFILE64_SOURCE=1 -DHAVE_HIDDEN -c -o compress.o compress.c
gcc -O3 -D_LARGEFILE64_SOURCE=1 -DHAVE_HIDDEN -c -o uncompr.o uncompr.c
gcc -O3 -D_LARGEFILE64_SOURCE=1 -DHAVE_HIDDEN -c -o gzclose.o gzclose.c
gcc -O3 -D_LARGEFILE64_SOURCE=1 -DHAVE_HIDDEN -c -o gzlib.o gzlib.c
gcc -O3 -D_LARGEFILE64_SOURCE=1 -DHAVE_HIDDEN -c -o gzread.o gzread.c
gcc -O3 -D_LARGEFILE64_SOURCE=1 -DHAVE_HIDDEN -c -o gzwrite.o gzwrite.c
ar rc libz.a adler32.o crc32.o deflate.o infback.o inffast.o inflate.o inftrees.o trees.o zutil.o compress.o uncompr.o gzclose.o gzlib.o gzread.o gzwrite.o
gcc -O3 -D_LARGEFILE64_SOURCE=1 -DHAVE_HIDDEN -o example example.o -L. libz.a
gcc -O3 -D_LARGEFILE64_SOURCE=1 -DHAVE_HIDDEN -I. -c -o minigzip.o test/minigzip.c
gcc -O3 -D_LARGEFILE64_SOURCE=1 -DHAVE_HIDDEN -o minigzip minigzip.o -L. libz.a
gcc -O3 -D_LARGEFILE64_SOURCE=1 -DHAVE_HIDDEN -I. -D_FILE_OFFSET_BITS=64 -c -o example64.o test/example.c
gcc -O3 -D_LARGEFILE64_SOURCE=1 -DHAVE_HIDDEN -o example64 example64.o -L. libz.a
gcc -O3 -D_LARGEFILE64_SOURCE=1 -DHAVE_HIDDEN -I. -D_FILE_OFFSET_BITS=64 -c -o minigzip64.o test/minigzip.c
gcc -O3 -D_LARGEFILE64_SOURCE=1 -DHAVE_HIDDEN -o minigzip64 minigzip64.o -L. libz.a
uos@uos-PC:/software/sharedlibrary/zlib/zlib-1.2.12$ make install
rm -f /software/sharedlibrary/zlib-static/lib/libz.a
cp libz.a /software/sharedlibrary/zlib-static/lib
chmod 644 /software/sharedlibrary/zlib-static/lib/libz.a
rm -f /software/sharedlibrary/zlib-static/share/man/man3/zlib.3
cp zlib.3 /software/sharedlibrary/zlib-static/share/man/man3
chmod 644 /software/sharedlibrary/zlib-static/share/man/man3/zlib.3
rm -f /software/sharedlibrary/zlib-static/lib/pkgconfig/zlib.pc
cp zlib.pc /software/sharedlibrary/zlib-static/lib/pkgconfig
chmod 644 /software/sharedlibrary/zlib-static/lib/pkgconfig/zlib.pc
rm -f /software/sharedlibrary/zlib-static/include/zlib.h /software/sharedlibrary/zlib-static/include/zconf.h
cp zlib.h zconf.h /software/sharedlibrary/zlib-static/include
chmod 644 /software/sharedlibrary/zlib-static/include/zlib.h /software/sharedlibrary/zlib-static/include/zconf.h
静态库工程代码结构
uos@uos-PC:/software/code/ziplib$ tree
.
├── build
├── CMakeLists.txt
├── CMakeLists.txt.user
├── src
│ ├── crc32.h
│ ├── crc32.o
│ ├── ioapi.o
│ ├── unzip.o
│ ├── zip.o
│ ├── zip_unzip.cpp
│ └── zip_unzip.h
编译
uos@uos-PC:/software/code/ziplib$ cd build && cmake ..
-- The CXX compiler identification is GNU 8.3.0
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /software/code/ziplib/build
uos@uos-PC:/software/code/ziplib/build$ make
Scanning dependencies of target ziplib
[ 50%] Building CXX object CMakeFiles/ziplib.dir/src/zip_unzip.cpp.o
[100%] Linking CXX static library libziplib.a
[100%] Built target ziplib
uos@uos-PC:/software/code/ziplib/build$ ls
CMakeCache.txt CMakeFiles cmake_install.cmake libziplib.a Makefile
main.cpp
#include
#include "src/zip_unzip.h"
int main(){
zip_unzip zip;
zip.add_file_to_zip_arrary("/software/test.txt");
zip.add_directory_to_zip_arrary("/software/ebook/");
zip.run_zip_arrary("/software/test1234.zip");
zip.run_unzip("/software/test1234.zip","/software/asbccddds/");
std::cout<<"ziplib\n";
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(test-zip LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
include_directories(ziplib/src)
include_directories(/software/sharedlibrary/zlib/zlib-1.2.12)
include_directories(${PROJECT_SOURCE_DIR})
find_library(ZLIB_A libziplib.a /software/code/ziplib/build NO_DEFAULT_PATH)
link_libraries(${ZLIB_A})
link_libraries(${SRC_ZLIB_A})
add_executable(zip-test
main.cpp
)
target_link_libraries(zip-test -fPIC
stdc++fs
)
编译-运行:
https://download.csdn.net/download/jiangyingfeng/85236650