最新消息:20210917 已从crifan.com换到crifan.org

【已解决,但不完美】实现WLW上传图片到WordPress过程中,自动翻译文件名

WLW crifan 2567浏览 0评论

几张图片,对应wlw中源码,被替换thumb后为:

<p><a href="$对应Exclue项中就新添了对应该网站的一个REG_BINARY类型的zero-length binary value_thumb.jpg" target="_blank"><img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="对应Exclue项中就新添了对应该网站的一个REG_BINARY类型的zero-length binary value" border="0" alt="对应Exclue项中就新添了对应该网站的一个REG_BINARY类型的zero-length binary value" src="$对应Exclue项中就新添了对应该网站的一个REG_BINARY类型的zero-length binary value_thumb.jpg" width="640" height="321" /></a>&#160;</p>

<p><a href="$点击 对应页面的叉号 remove this page_thumb.jpg" target="_blank"><img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="点击 对应页面的叉号 remove this page" border="0" alt="点击 对应页面的叉号 remove this page" src="$点击 对应页面的叉号 remove this page_thumb.jpg" width="274" height="188" /></a></p>

<p><a href="$全选 右键 delete_thumb.jpg" target="_blank"><img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="全选 右键 delete" border="0" alt="全选 右键 delete" src="$全选 右键 delete_thumb.jpg" width="640" height="325" /></a></p>

<p><a href="$再选择yes 即可删除所有 之前已被排除的网页_thumb.jpg" target="_blank"><img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="再选择yes 即可删除所有 之前已被排除的网页" border="0" alt="再选择yes 即可删除所有 之前已被排除的网页" src="$再选择yes 即可删除所有 之前已被排除的网页_thumb.jpg" width="640" height="321" /></a></p>

<p><a href="$变成这样的空的只剩Default的_thumb.jpg" target="_blank"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="变成这样的空的只剩Default的" border="0" alt="变成这样的空的只剩Default的" src="$变成这样的空的只剩Default的_thumb.jpg" width="640" height="321" /></a></p>

然后实际上的html为:

<P><A 
href="file:///C:/Users/CLi/AppData/Local/Temp/WindowsLiveWriter2049324412/supfiles11F069A/对应Exclue项中就新添了对应该网站的一个REG_BINARY类型的zero-length binary value[2].jpg"><IMG 
style="BACKGROUND-IMAGE: none; BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px; PADDING-TOP: 0px" 
title="对应Exclue项中就新添了对应该网站的一个REG_BINARY类型的zero-length binary value" border=0 
alt="对应Exclue项中就新添了对应该网站的一个REG_BINARY类型的zero-length binary value" 
src="file:///C:/Users/CLi/AppData/Local/Temp/WindowsLiveWriter2049324412/supfiles11F069A/对应Exclue项中就新添了对应该网站的一个REG_BINARY类型的zero-length binary value_thumb.jpg" 
width=928 height=466></A>&nbsp;</P>
<P><A 
href="file:///C:/Users/CLi/AppData/Local/Temp/WindowsLiveWriter2049324412/supfiles11F069A/点击 对应页面的叉号 remove this page[2].jpg"><IMG 
style="BACKGROUND-IMAGE: none; BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px; PADDING-TOP: 0px" 
title="点击 对应页面的叉号 remove this page" border=0 alt="点击 对应页面的叉号 remove this page" 
src="file:///C:/Users/CLi/AppData/Local/Temp/WindowsLiveWriter2049324412/supfiles11F069A/点击 对应页面的叉号 remove this page_thumb.jpg" 
width=274 height=188></A></P>
<P><A 
href="file:///C:/Users/CLi/AppData/Local/Temp/WindowsLiveWriter2049324412/supfiles11F069A/全选 右键 delete[2].jpg"><IMG 
style="BACKGROUND-IMAGE: none; BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px; PADDING-TOP: 0px" 
title="全选 右键 delete" border=0 alt="全选 右键 delete" 
src="file:///C:/Users/CLi/AppData/Local/Temp/WindowsLiveWriter2049324412/supfiles11F069A/全选 右键 delete_thumb.jpg" 
width=925 height=470></A></P>
<P><A 
href="file:///C:/Users/CLi/AppData/Local/Temp/WindowsLiveWriter2049324412/supfiles11F069A/再选择yes 即可删除所有 之前已被排除的网页[2].jpg"><IMG 
style="BACKGROUND-IMAGE: none; BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px; PADDING-TOP: 0px" 
title="再选择yes 即可删除所有 之前已被排除的网页" border=0 alt="再选择yes 即可删除所有 之前已被排除的网页" 
src="file:///C:/Users/CLi/AppData/Local/Temp/WindowsLiveWriter2049324412/supfiles11F069A/再选择yes 即可删除所有 之前已被排除的网页_thumb.jpg" 
width=929 height=467></A></P>
<P><A 
href="file:///C:/Users/CLi/AppData/Local/Temp/WindowsLiveWriter2049324412/supfiles11F069A/变成这样的空的只剩Default的[2].jpg"><IMG 
style="BACKGROUND-IMAGE: none; BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px; PADDING-TOP: 0px" 
title=变成这样的空的只剩Default的 border=0 alt=变成这样的空的只剩Default的 
src="file:///C:/Users/CLi/AppData/Local/Temp/WindowsLiveWriter2049324412/supfiles11F069A/变成这样的空的只剩Default的_thumb.jpg" 
width=928 height=466></A></P>

 

现在的问题是,当本地的图片,比如:

C:/Users/CLi/AppData/Local/Temp/WindowsLiveWriter2049324412/supfiles11F069A/对应Exclue项中就新添了对应该网站的一个REG_BINARY类型的zero-length binary value_thumb.jpg

C:/Users/CLi/AppData/Local/Temp/WindowsLiveWriter2049324412/supfiles11F069A/点击 对应页面的叉号 remove this page_thumb.jpg

C:/Users/CLi/AppData/Local/Temp/WindowsLiveWriter2049324412/supfiles11F069A/全选 右键 delete_thumb.jpg

C:/Users/CLi/AppData/Local/Temp/WindowsLiveWriter2049324412/supfiles11F069A/再选择yes 即可删除所有 之前已被排除的网页_thumb.jpg

C:/Users/CLi/AppData/Local/Temp/WindowsLiveWriter2049324412/supfiles11F069A/变成这样的空的只剩Default的_thumb.jpg

 

通过WLW上传到Wordpress上面,作为当前post的附件时,上传之后的文件名为:

ExclueREG_BINARYzero-length-binary-value_thumb.jpg

remove-this-page_thumb.jpg

delete_thumb.jpg

yes-_thumb.jpg

Default_thumb.jpg

很明显,文件名部分中的中文,都丢失了,只剩下英文了。

如此一来,上传上去的文件,名字不仅丢失了原先的含义,并且容易导致文件名冲突,因为名字都变得很短,没有确切的含义了。

现在希望是,当上传这些文件时,自动帮忙翻译一下,比如利用google的翻译功能:

http://translate.google.cn

将上述的:

对应Exclue项中就新添了对应该网站的一个REG_BINARY类型的zero-length binary value_thumb

翻译为:

The on new corresponding Exclue item zero-length binary value_thumb should be the site of a REG_BINARY type

这样,不仅文件名有了对应的含义,且也去掉了thumb这个无意义的字眼了。

【解决过程】

1.看起来,要去找,对于wordpress来说,自动通过XML-RPC上传post的附件时,文件名是如何设置的。

想办法,在此上传的文件名过程中,先翻译,然后设置为新的文件名。

2.打算先在本地的wordpress中测试。

然后想到,好像这些图片上传上去,都是作为当前post的附件上传的。

所以wlw中看到的源码中的图片文件名,都是$xxx.jpg,而不是

https://www.crifan.org/files/pic/uploads/2012/10/xxx.png

的。

而且应该是利用wordpress中的XML-RPC的某些接口,实现附件上传的。

3. 所以,去学习

http://codex.wordpress.org/XML-RPC_Support

然后竟然可以找到,其有接口供你扩展:

http://codex.wordpress.org/XML-RPC_Extending

貌似,可以通过实现此扩展,来实现对于上传图片的文件名自动翻译的效果。

4. 接着也就可以找到XMP-RPC所对应的wordpress中的实现:

wp-includes\class-wp-xmlrpc-server.php

然后搜attach,也可以找到很多变量和函数的。

找到一个attach_uploads,貌似是用来上传附件的。

5.然后就是去class-wp-xmlrpc-server.php添加调试代码,来一点点找到具体哪些函数被调用了。

然后当随便添加一句:

print("call xxx_newPost");

到对应的xxx_newPost函数中去,最后发帖出现失败,可以最后定位,调用的是

metaWeblog.newMediaObject

所以可以找到:

‘metaWeblog.newMediaObject’ => ‘this:mw_newMediaObject’,

确定是调用的mw_newMediaObject。

6.然后接着参考:

http://codex.wordpress.org/Debugging_in_WordPress

去把

wp-config.php

中的

define(‘WP_DEBUG’, false);

改为:

define(‘WP_DEBUG’, true);

刷新页面,可以看到对应的debug信息:

see debug info

但是结果再去发帖,结果竟然失败了:

从日志服务器接收的对 metaWeblog.newMediaObject 方法的响应无效:

Invalid response document returned from XmlRpc server

从日志服务器接收的对 metaWeblog.newMediaObject 方法的响应无效

 

而相关的代码是:

	/**
	 * Uploads a file, following your settings.
	 *
	 * Adapted from a patch by Johann Richard.
	 *
	 * @link http://mycvs.org/archives/2004/06/30/file-upload-to-wordpress-in-ecto/
	 *
	 * @since 1.5.0
	 *
	 * @param array $args Method parameters.
	 * @return array
	 */
	function mw_newMediaObject($args) {
		global $wpdb;

		$blog_ID     = (int) $args[0];
		$username  = $wpdb->escape($args[1]);
		$password   = $wpdb->escape($args[2]);
		$data        = $args[3];

		$name = sanitize_file_name( $data['name'] );
		$type = $data['type'];
		$bits = $data['bits'];

		if ( !$user = $this->login($username, $password) )
			return $this->error;

		do_action('xmlrpc_call', 'metaWeblog.newMediaObject');

		if ( !current_user_can('upload_files') ) {
			$this->error = new IXR_Error( 401, __( 'You do not have permission to upload files.' ) );
			return $this->error;
		}

		if ( $upload_err = apply_filters( 'pre_upload_error', false ) )
			return new IXR_Error(500, $upload_err);

		if ( !empty($data['overwrite']) && ($data['overwrite'] == true) ) {
			// Get postmeta info on the object.
			$old_file = $wpdb->get_row("
				SELECT ID
				FROM {$wpdb->posts}
				WHERE post_title = '{$name}'
					AND post_type = 'attachment'
			");

			// Delete previous file.
			wp_delete_attachment($old_file->ID);

			// Make sure the new name is different by pre-pending the
			// previous post id.
			$filename = preg_replace('/^wpid\d+-/', '', $name);
			$name = "wpid{$old_file->ID}-{$filename}";
		}

		$upload = wp_upload_bits($name, null, $bits);
		if ( ! empty($upload['error']) ) {
			$errorString = sprintf(__('Could not write file %1$s (%2$s)'), $name, $upload['error']);
			return new IXR_Error(500, $errorString);
		}
		// Construct the attachment array
		// attach to post_id 0
		$post_id = 0;
		$attachment = array(
			'post_title' => $name,
			'post_content' => '',
			'post_type' => 'attachment',
			'post_parent' => $post_id,
			'post_mime_type' => $type,
			'guid' => $upload[ 'url' ]
		);

		// Save the data
		$id = wp_insert_attachment( $attachment, $upload[ 'file' ], $post_id );
		wp_update_attachment_metadata( $id, wp_generate_attachment_metadata( $id, $upload['file'] ) );

		do_action( 'xmlrpc_call_success_mw_newMediaObject', $id, $args );

		$struct = array(
			'id'   => strval( $id ),
			'file' => $name,
			'url'  => $upload[ 'url' ],
			'type' => $type
		);
		return apply_filters( 'wp_handle_upload', $struct, 'upload' );
	}

 

很明显,变成了,打开了wordpress的debug,竟然导致发帖时附件无法上传了。

7.其中,上述代码中,也很容易看出其代码的逻辑,就是上传对应的附件,生成对应附件的id,然后把此附件和post关联等。

其中,很明显,我所需要关心的,是这段:

$name = sanitize_file_name( $data[‘name’] );

然后又去找到官网对sanitize_file_name的解释:

http://codex.wordpress.org/Function_Reference/sanitize_file_name

Function Reference/sanitize file name

Description

Sanitizes a filename replacing whitespace with dashes

Removes special characters that are illegal in filenames on certain operating systems and special characters requiring special escaping to manipulate at the command line. Replaces spaces and consecutive dashes with a single dash. Trim period, dash and underscore from beginning and end of filename.

Usage

<?php sanitize_file_name( $name ) ?>

所以,应该就是这里,对于之前所上传的中文的文件名,都处理称为,把中文汉字去掉,把空格变为短横线。

比如,把

可以启动Ghost 11.0.2.png

变为:

Ghost-11.0.21.png

8.后来就是一堆的调试。

期间遇到个php错误,也解决掉了:

【已解决】wordpress中,调用自定义的函数时出现错误:PHP Fatal error: Call to undefined function xxx() in yyy.php

9.然后对于如下代码:

    /**
     * Translate and sannitize filename
     *
     * If is zh-CN, then translate it to en
     * If is en, then relace them into
     *
     * @param string $orig_file_name Method parameters.
     * @return string
     */
    function translate_sanitize_file_name($orig_file_name) {
        $new_file_name = $orig_file_name;
        
        //$rand_val = rand(1, 100000);
        $rand_val = rand();
        $new_file_name = "fake_name_test".strval($rand_val);
        //$new_file_name = "fake_name_test";
        
        $new_file_name = sanitize_file_name($new_file_name);
        
        return $new_file_name;
    }
    
    
	/**
	 * Uploads a file, following your settings.
	 *
	 * Adapted from a patch by Johann Richard.
	 *
	 * @link http://mycvs.org/archives/2004/06/30/file-upload-to-wordpress-in-ecto/
	 *
	 * @since 1.5.0
	 *
	 * @param array $args Method parameters.
	 * @return array
	 */
	function mw_newMediaObject($args) {
		global $wpdb;

		$blog_ID     = (int) $args[0];
		$username  = $wpdb->escape($args[1]);
		$password   = $wpdb->escape($args[2]);
		$data        = $args[3];

		//$name = sanitize_file_name( $data['name'] );
        //print($name);
        //echo($name);
        $name = $this->translate_sanitize_file_name( $data['name'] );
        //$name = "fake_name_test_12";
		$type = $data['type'];
		$bits = $data['bits'];

最后发布带图片的测试帖子时,出现这样的错误:

日志不支持图片发布

后来再折腾,添加了后缀,改为:

    /**
     * Translate and sannitize filename
     *
     * If is zh-CN, then translate it to en
     * If is en, then relace them into
     *
     * @param string $orig_file_name Method parameters.
     * @return string
     */
    function translate_sanitize_file_name($orig_file_name) {
        $new_file_name = $orig_file_name;
        
        //$rand_val = rand(1, 100000);
        $rand_val = rand();
        $new_file_name = "fake_name_test".strval($rand_val).".png";
        //$new_file_name = "fake_name_test";
        
        $new_file_name = sanitize_file_name($new_file_name);
        
        return $new_file_name;
    }
    
    
	/**
	 * Uploads a file, following your settings.
	 *
	 * Adapted from a patch by Johann Richard.
	 *
	 * @link http://mycvs.org/archives/2004/06/30/file-upload-to-wordpress-in-ecto/
	 *
	 * @since 1.5.0
	 *
	 * @param array $args Method parameters.
	 * @return array
	 */
	function mw_newMediaObject($args) {
		global $wpdb;

		$blog_ID     = (int) $args[0];
		$username  = $wpdb->escape($args[1]);
		$password   = $wpdb->escape($args[2]);
		$data        = $args[3];

		//$name = sanitize_file_name( $data['name'] );
        //print($name);
        //echo($name);
        $name = $this->translate_sanitize_file_name( $data['name'] );
        //$name = "fake_name_test_12";
		$type = $data['type'];
		$bits = $data['bits'];

然后就可以正常发布了。

(后来通过:

采用metaWeblog.newMediaObject方法发送图片到wordpress中

这里也看到了类似的提示了:

name参数一定要带上扩展名,否则会出错(无法写入文件 无效的文件类型)

发布出来的图片的地址,就是类似于这样的:

http://localhost/files/pic/uploads/2012/10/fake_name_test10547.png

其中文件名fake_name_test10547.png是我们刚才代码里面生成的。

10.后来,就又总结出了相关的调试方法:

【整理】如何调试wordpress中的php代码 + 注意事项

11.最后,经过一番调试,得到的结果是,在class-wp-xmlrpc-server.php中,mw_newMediaObject被调用时,此时

$data        = $args[3];

$data[‘name’]就已经是对应的文件名了,即,

当本地的,wlw中的源码的图片名是中文,比如“彭德怀_thumb.png”时,则经过wlw处理后,上传上去的,貌似就已经变成:_thumb.png了。

所以,此处想要实现的,从“彭德怀_thumb.png"翻译为自己想要的英文名,就无法实现了。

12.不过,倒是想起来了,看看是否可以利用

metaWeblog.newMediaObject

中,传递额外的参数中,获得所需的alt字符串,然后参考:

http://xmlrpc.scripting.com/metaWeblogApi.html

得知:

metaWeblog.newMediaObject (blogid, username, password, struct) returns struct

所以,此处代码中的

	function mw_newMediaObject($args) {
		global $wpdb;
        

		$blog_ID     = (int) $args[0];
		$username  = $wpdb->escape($args[1]);
		$password   = $wpdb->escape($args[2]);
		$data        = $args[3];

中的$data,就是对应的struct了。

然后就想去看看到底当前传递进来的data,到底有几个域,看看能否有多余的域供利用。

结果通过参考:

获取php数组的键名和值

去使用

error_log(print_r(array_keys ($data), true));

打印出当前的data的域:

[26-Oct-2012 09:03:40] Array
(
    [0] => name
    [1] => type
    [2] => bits
)

只有这三个,所以,没有额外的域可以利用。

所以,目前的结论是,对于wlw中,会自动把图片的中文名干掉,过滤掉,只剩下_thumb.png之类的名字,传递到mw_newMediaObject中,所以mw_newMediaObject中是无法获得对应的图片文件的中文名,无法实现翻译的功能的。

13.所以,剩下能走得通的办法,估计还是去写wlw的插件,在文章发布之后,再去修改当前post的图片附件的文件名。

或者是发布之前,想办法改文件名了。但是在发布前改文件名的办法,已经试过了,结果遇到图片正在被进程所使用,无法修改。

但是此刻,突然想到一个规避的办法,试着重新拷贝出一份图片,然后把图片名字翻译后,再改文件名,也许就可以了。

14. 所以,可以接着去折腾之前的插件:

http://code.google.com/p/picturemanager/

了。

15.最后的折腾的结果:

拷贝文件是可以的,但是还是无法解决避免wlw生成双份图片。

即使写代码,按照其最后wlw对于单个文件所产生的结果:

对于原先的src的图片xxx_thumb.jpg,生成对应的xxx.jpg,xxx[1].jpg,xxx[2].jpg,xxx[3].jpg,然后再把href值换为src,

结果插件执行完毕返回wlw中,wlw还是会针对xxx_thumb.jpg作为一个新的文件,然后生成xxx_thumb.jpg,xxx_thumb[1].jpg,xxx_thumb[2].jpg,xxx_thumb[3].jpg。

所以,最后只能彻底放弃wlw中模拟wlw的方式,只能换用另外的分两步骤的方法:

先是将中文名翻译为英文名;

然后回到wlw后,其会自动将href替换为src中对应的已翻译后的文件名,以及也会也把title和alt换为翻译后的文件名;

接着再去使用原先的那些功能,包括添加target="_blank",自动缩放,把href换为src;

最终,间接地实现了,只保留wlw中单张图片的效果。

对于每次生成的图片,文件名都带了个_thumb这点,还是有点不爽的。也曾想过,通过修改mw_newMediaObject,在其中去判断文件名,如果是xxx_thumb的文件名,且xxx不为空的话,那么自动去掉_thumb。

此法也是可行的,但却是为了最终的目标,而折腾了wlw中单个插件,运行2次之外,再修改wordpress源码,这样的最终方案,也太繁琐,所以就放弃修改wordpress中的mw_newMediaObject了。暂时忍受文件名都带个_thumb吧。

 

【总结】

总之,为了实现,本地wlw中的图片,上传到wordpress中时,文件名可以自动翻译,且保持不重复上传,目前,相对来说,最能接受的方法,只能是使用自己写的这个插件了:

http://code.google.com/p/picturemanager/

而且使用起来其实也是麻烦的:

如果需要翻译,先要运行,点击Translate

然后再重新运行,点击Process

才能达到最终的效果的。

期待以后,能找到更加完美的解决方案。

转载请注明:在路上 » 【已解决,但不完美】实现WLW上传图片到WordPress过程中,自动翻译文件名

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
92 queries in 0.185 seconds, using 23.39MB memory