WordPress通过Rest API自定义附件上传接口

本站所有文章均为博主人工写作,绝无AI辅助成分,请放心参阅。

有没有想过用WordPress来建立自己的文件存储空间,当作自己的网盘使用?这个业务实现的主要逻辑其实就是自己写一个Rest API接口上传文件到WP的媒体库中。

首先我们需要安装一个插件,这个插件很小,只是给网站后台登录提供Basic认证,并不是用来拓展业务接口的。开通了Basic认证方式,我们才有途径获得使用Rest API更新网站内容的权限,否则Rest API只提供读取权限。插件名称叫做JSON Basic Authentication,官方下载地址:https://github.com/WP-API/Basic-Auth

要做接口,就先创建endpoint。这次我创建两个,一个是用来转存网上的文件的,一个是用来自己上传文件的。

add_action( 'rest_api_init', function () {
	//如果你不打算把文件存到WP默认的位置,这是修改位置的钩子
	add_filter( 'upload_dir', 'brain1981_upload_dir');
 
	//转存
	register_rest_route( 'brain1981/v1', '/catch/', array(
		'methods' => 'POST',
		'callback' => 'brain1981_api_post_catch',
	) );
	//上传
	register_rest_route( 'brain1981/v1', '/stream/', array(
		'methods' => 'POST',
		'callback' => 'brain1981_api_post_stream',
	) );
});

如果你不打算把文件存到WP默认的位置,这是修改位置的函数

function brain1981_upload_dir( $param ){
	// 指定子目录名称
	$mydir = '/my-path';
 
	// 在默认位置(WP后台设定的年份和月份文件夹)下新建my-path子目录存储文件
	$param['path'] = $param['path'] . $mydir;
	$param['url'] = $param['url'] . $mydir;
	return $param;
 
	// 存到uploads下的my-path子目录
	// $param['path']    = $param['basedir'] . $mydir;
	// $param['url']     = $param['baseurl'] . $mydir;
	// return $param;
}

接下来是处理函数

转存文件

function brain1981_api_post_catch($request){
	$file_url = $request['url'];
	//如有需要,可以给所有通过这个接口存储的文件名加一个前缀
	$file_prefix = 'prefix_';
	$file_content=file_get_contents($file_url);
	$url_api = site_url("/wp-json/wp/v2/media/");
	$file_name = $request['filename'];
	$ch = curl_init();
	curl_setopt($ch, CURLOPT_URL,            $url_api );
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1 );
	curl_setopt($ch, CURLOPT_POST,           1 );
	curl_setopt($ch, CURLOPT_POSTFIELDS,     $file_content); 
	curl_setopt($ch, CURLOPT_HTTPHEADER,     array(
		'content-disposition: attachment; filename='.$file_prefix.$file_name.'"',
		'authorization: ' . $_SERVER['HTTP_AUTHORIZATION']
		)
	); 
	$result=curl_exec($ch);
	if(json_decode($result)->id){
		return json_decode($result)->guid->rendered ;
	}else{
		return json_decode($result)->data->status . " " .json_decode($result)->message;
	}
 
}

上传文件

function brain1981_api_post_stream($request){
	$file_content = $request['content'];
	$file_content = base64_decode($file_content);
	$file_name = $request['filename'];
 
	//如有需要,可以给所有通过这个接口存储的文件名加一个前缀
	$file_prefix = 'prefix_';
 
	$url_api = site_url("/wp-json/wp/v2/media/");
 
	if(!empty($request['mime'])){
		$mime = $request['mime'];
	}else{
		$mime="text/plain";
	}
 
 
	$file_name = $request['filename'];
	$ch = curl_init();
	curl_setopt($ch, CURLOPT_URL,            $url_api );
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1 );
	curl_setopt($ch, CURLOPT_POST,           1 );
	curl_setopt($ch, CURLOPT_POSTFIELDS,     $file_content); 
	curl_setopt($ch, CURLOPT_HTTPHEADER,     array(
		'content-disposition: attachment; filename='.$file_prefix.$file_name,
		'cache-control: no-cache',
		'authorization: ' . $_SERVER['HTTP_AUTHORIZATION'],
		'content-type: ' . $mime
		)
	); 
	$result=curl_exec($ch);
	if(json_decode($result)->id){
		return json_decode($result)->guid->rendered ;
	}else{
		return json_decode($result)->data->status . " " .json_decode($result)->message." ";
	}
}

这样接口就建立完毕了,下面是如何请求这两个接口。
转存文件,接口URL: http(s)://网站域名/wp-json/brain1981/v1/catch/
请求格式为JSON:

{
    "url": "附件的url地址,需包含http://或https://",
    "filename": "文件名"
}

直接上传文件,接口URL: http(s)://网站域名/wp-json/brain1981/v1/stream/
请求格式:

{
    "content": "数据流内容..数据流内容",
    "filename": "文件名",
    "mime": "文件格式"
}

请求格式的注意点:
– 请注意JSON最后一行不能有逗号
– 视服务器条件而定,服务器会有一定的响应时间限制,原则上应该无法接受超过50M的数据(LNMP默认环境),过大的数据流会造成超时和发送失败
– filename文件名请包含合法的扩展名,暂只支持jpg,gif、png、pdf等常见格式
– mime文件格式:填写对应文件的格式,如“image/jpeg”、“image/png”、“image/gif”、“application/pdf”、“application/pdf”或“text/plain”
– content数据流的内容,可以直接把文件通过二进制数据写到这个JSON中

接下来我们需要通过Basic认证获取API的权限,再使用上面写出来的接口上传文件。
获取权限,就要在请求的头部把登录信息转换成Base64字符串,具体格式是这样的:
Authorization: Basic {base64_encode([username]:[password])}
Content-Type: application/json

提供一个JS的范例,用来转存文件:

$.ajax({
    url: 'http(s)://网站域名/wp-json/brain1981/v1/catch/',
    method: 'POST',
    crossDomain: true,
    data: {
        "url": "http://xxx.xxx/abc.jpg",
        "filename": "xyz.jpg"
    },
    beforeSend: function ( xhr ) {
         //以下这行要改成自己真实的用WP户名和密码,并且账号需具有editor或以上权限
        xhr.setRequestHeader( 'Authorization', 'Basic ' + Base64.encode( 'username:password' ) );
    },
    success: function( data, txtStatus, xhr ) {
        console.log( data );
        console.log( xhr.status );
    }
});
//认证字符串的Base64编码库
var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(e){var t="";var n,r,i,s,o,u,a;var f=0;e=Base64._utf8_encode(e);while(f<e.length){n=e.charCodeAt(f++);r=e.charCodeAt(f++);i=e.charCodeAt(f++);s=n>>2;o=(n&3)<<4|r>>4;u=(r&15)<<2|i>>6;a=i&63;if(isNaN(r)){u=a=64}else if(isNaN(i)){a=64}t=t+this._keyStr.charAt(s)+this._keyStr.charAt(o)+this._keyStr.charAt(u)+this._keyStr.charAt(a)}return t},decode:function(e){var t="";var n,r,i;var s,o,u,a;var f=0;e=e.replace(/[^A-Za-z0-9\+\/\=]/g,"");while(f<e.length){s=this._keyStr.indexOf(e.charAt(f++));o=this._keyStr.indexOf(e.charAt(f++));u=this._keyStr.indexOf(e.charAt(f++));a=this._keyStr.indexOf(e.charAt(f++));n=s<<2|o>>4;r=(o&15)<<4|u>>2;i=(u&3)<<6|a;t=t+String.fromCharCode(n);if(u!=64){t=t+String.fromCharCode(r)}if(a!=64){t=t+String.fromCharCode(i)}}t=Base64._utf8_decode(t);return t},_utf8_encode:function(e){e=e.replace(/\r\n/g,"\n");var t="";for(var n=0;n<e.length;n++){var r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r)}else if(r>127&&r<2048){t+=String.fromCharCode(r>>6|192);t+=String.fromCharCode(r&63|128)}else{t+=String.fromCharCode(r>>12|224);t+=String.fromCharCode(r>>6&63|128);t+=String.fromCharCode(r&63|128)}}return t},_utf8_decode:function(e){var t="";var n=0;var r=c1=c2=0;while(n<e.length){r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r);n++}else if(r>191&&r<224){c2=e.charCodeAt(n+1);t+=String.fromCharCode((r&31)<<6|c2&63);n+=2}else{c2=e.charCodeAt(n+1);c3=e.charCodeAt(n+2);t+=String.fromCharCode((r&15)<<12|(c2&63)<<6|c3&63);n+=3}}return t}};

2022年2月7日更新:增加了修改存放目录的代码
–全文完–

本站所有文章均为原创,欢迎转载,请注明文章出处:https://blog.brain1981.com/2194.html。百度和各类采集站皆不可信,搜索请谨慎鉴别。技术类文章一般都有时效性,本人习惯不定期对自己的博文进行修正和更新,因此请访问出处以查看本文的最新版本。

关注我们的微信公众号-JennyStudio 本站记录了近几年的工作中遇到的一些技术问题和解决过程,“作品集”还收录了本人的大部分作品展示。除了本博客外,我们的工作室网站 – JennyStudio,内有更多作品回顾和展示。
您也可以扫描左边的二维码,关注我们的微信公众号,在微信上查看我们的案例。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注