This page is a translated version of the page API:Upload and the translation is 100% complete.
MediaWiki版本:
1.16

使用POST请求来上传一个文件。

有三种方法通过API上传文件:

  1. 直接上传本地文件
  2. 从URL复制上传一个文件
  3. 分块上传一个本地文件

所有这些方法需要一个拥有upload权限的账号。

API帮助文档

action=upload

(main | upload)
  • This module requires read rights.
  • This module requires write rights.
  • This module only accepts POST requests.
  • Source: MediaWiki
  • License: GPL-2.0-or-later

Upload a file, or get the status of pending uploads.

Several methods are available:

  • Upload file contents directly, using the file parameter.
  • Upload the file in pieces, using the filesize, chunk, and offset parameters.
  • Have the MediaWiki server fetch a file from a URL, using the url parameter.
  • Complete an earlier upload that failed due to warnings, using the filekey parameter.

Note that the HTTP POST must be done as a file upload (i.e. using multipart/form-data) when sending the file.

Specific parameters:
Other general parameters are available.
filename

Target filename.

comment

Upload comment. Also used as the initial page text for new files if text is not specified.

Default: (empty)
tags

Change tags to apply to the upload log entry and file page revision.

Values (separate with | or alternative): AWB, convenient-discussions
text

Initial page text for new files.

watch
Deprecated.

Watch the page.

Type: boolean (details)
watchlist

Unconditionally add or remove the page from the current user's watchlist, use preferences (ignored for bot users) or do not change watch.

One of the following values: nochange, preferences, watch
Default: preferences
watchlistexpiry

Watchlist expiry timestamp. Omit this parameter entirely to leave the current expiry unchanged.

Type: expiry (details)
ignorewarnings

Ignore any warnings.

Type: boolean (details)
file

File contents.

Must be posted as a file upload using multipart/form-data.
url

URL to fetch the file from.

filekey

Key that identifies a previous upload that was stashed temporarily.

sessionkey
Deprecated.

Same as filekey, maintained for backward compatibility.

stash

If set, the server will stash the file temporarily instead of adding it to the repository.

Type: boolean (details)
filesize

Filesize of entire upload.

Type: integer
The value must be between 0 and 5,368,709,120.
offset

Offset of chunk in bytes.

Type: integer
The value must be no less than 0.
chunk

Chunk contents.

Must be posted as a file upload using multipart/form-data.
async

Make potentially large file operations asynchronous when possible.

Type: boolean (details)
checkstatus

Only fetch the upload status for the given file key.

Type: boolean (details)
token

A "csrf" token retrieved from action=query&meta=tokens

This parameter is required.


上傳警告

请注意,由于许多警告条件,上传可能会失败。这可以通过设置 ignorewarnings=1 来覆盖。以下列举了一些值得注意的警告:

  • exists: 存在同名文件。如果忽略此警告,上传的文件将替换现有文件。
    • no-change: 存在同名且内容一致的文件。
    • duplicateversions: 存在同名文件,且您上传的文件是已存在文件的一个较旧版本。
  • was-deleted: 存在已被删除的同名文件。
  • duplicate: 您要上传的文件在站点中已有同名(或不同名)版本。上传这个文件的副本可能是不可取的。
  • duplicate-archive: 您要上传的文件在站点中曾经以不同(或相同)的名称存在,但已被删除。这可能表明该文件不合适且不应上传。
  • badfilename: 提供的文件名在此wiki上不可接受,例如因为其包含禁用字符
结果
{
  "upload": {
    "result": "Warning",
    "warnings": {
      "badfilename": "My_bad:filename.png"
    },
    "filekey": "19mmz8arzreg.9md1cj.2283740.png",
    "sessionkey": "19mmz8arzreg.9md1cj.2283740.png"
  }
}


示例

任何POST请求都是一个多步骤的过程:

  1. 使用API:登录 中描述的方法之一登录。
  2. 获取CSRF令牌
  3. 发送包含CSRF令牌的POST请求以上传文件。

示例一:直接上传本地文件

直接上传文件时,请求必须使用 multipart/form-data 作为content-type或enctype,同时 application/x-www-form-urlencoded 不起作用。

POST请求

响应

结果
{
	"upload": {
		"filename": "File_1.jpg",
		"result": "Success",
		"imageinfo": {
			"url": "https://upload.wikimedia.org/wikipedia/test/3/39/File_1.jpg",
			"html": "<p>A file with this name exists already, please check <strong><a class=\"mw-selflink selflink\">File:File 1.jpg</a></strong> if you are not sure if you want to change it.\n</p>\n<div class=\"thumb tright\"><div class=\"thumbinner\" style=\"width:182px;\"><a           href=\"/w/index.php?title=Special:Upload&amp;wpDestFile=File_1.jpg\" class=\"new\" title=\"File:File 1.jpg\">File:File 1.jpg</a>  <div class=\"thumbcaption\"></div></div></div>\n",
			"width": 474,
			"size": 26703,
			"bitdepth": 8,
			"mime": "image/jpeg",
			"userid": 42588,
			"mediatype": "BITMAP",
			"descriptionurl": "https://test.wikipedia.org/wiki/File:File_1.jpg",
			"extmetadata": {
				"ObjectName": {
					"value": "File 1",
					"hidden": "",
					"source": "mediawiki-metadata"
				},
				"DateTime": {
					"value": "2019-03-06 08:43:37",
					"hidden": "",
					"source": "mediawiki-metadata"
				}
				...
			},
			"comment": "",
			"commonmetadata": [],
			"descriptionshorturl": "https://test.wikipedia.org/w/index.php?curid=0",
			"sha1": "2ffadd0da73fab31a50407671622fd6e5282d0cf",
			"parsedcomment": "",
			"metadata": [
				{
					"name": "MEDIAWIKI_EXIF_VERSION",
					"value": 2
				}
			],
			"canonicaltitle": "File:File 1.jpg",
			"user": "Mansi29ag",
			"timestamp": "2019-03-06T08:43:37Z",
			"height": 296
		}
	}
}

示例代码

Python

"""
    upload_file_directly.py

    MediaWiki API Demos
    Demo of `Upload` module: Sending post request to upload a file directly

    MIT license
"""

import requests

S = requests.Session()
URL = "https://test.wikipedia.org/w/api.php"
FILE_PATH = 'f.jpg'

# Step 1: Retrieve a login token
PARAMS_1 = {
    "action": "query",
    "meta": "tokens",
    "type": "login",
    "format": "json"
}

R = S.get(url=URL, params=PARAMS_1)
DATA = R.json()

LOGIN_TOKEN = DATA["query"]["tokens"]["logintoken"]

# Step 2: Send a post request to login. Use of main account for login is not
# supported. Obtain credentials via Special:BotPasswords
# (https://www.mediawiki.org/wiki/Special:BotPasswords) for lgname & lgpassword
PARAMS_2 = {
    "action": "login",
    "lgname": "bot_username",
    "lgpassword": "bot_password",
    "format": "json",
    "lgtoken": LOGIN_TOKEN
}

R = S.post(URL, data=PARAMS_2)

# Step 3: Obtain a CSRF token
PARAMS_3 = {
    "action": "query",
    "meta":"tokens",
    "format":"json"
}

R = S.get(url=URL, params=PARAMS_3)
DATA = R.json()

CSRF_TOKEN = DATA["query"]["tokens"]["csrftoken"]

# Step 4: Post request to upload a file directly
PARAMS_4 = {
    "action": "upload",
    "filename": "file_1.jpg",
    "format": "json",
    "token": CSRF_TOKEN,
    "ignorewarnings": 1
}

FILE = {'file':('file_1.jpg', open(FILE_PATH, 'rb'), 'multipart/form-data')}

R = S.post(URL, files=FILE, data=PARAMS_4)
DATA = R.json()
print(DATA)

PHP

<?php

/*
    upload_file_directly.php

    MediaWiki API Demos
	Demo of `Upload` module: Sending post request to upload a file directly

    MIT license
*/

$endPoint = "https://test.wikipedia.org/w/api.php";

$login_Token = getLoginToken(); // Step 1
loginRequest( $login_Token ); // Step 2
$csrf_Token = getCSRFToken(); // Step 3
upload( $csrf_Token ); // Step 4

// Step 1: GET request to fetch login token
function getLoginToken() {
	global $endPoint;

	$params1 = [
		"action" => "query",
		"meta" => "tokens",
		"type" => "login",
		"format" => "json"
	];

	$url = $endPoint . "?" . http_build_query( $params1 );

	$ch = curl_init( $url );
	curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
	curl_setopt( $ch, CURLOPT_COOKIEJAR, "cookie.txt" );
	curl_setopt( $ch, CURLOPT_COOKIEFILE, "cookie.txt" );

	$output = curl_exec( $ch );
	curl_close( $ch );

	$result = json_decode( $output, true );
	return $result["query"]["tokens"]["logintoken"];
}

// Step 2: POST request to log in. Use of main account for login is not
// supported. Obtain credentials via Special:BotPasswords
// (https://www.mediawiki.org/wiki/Special:BotPasswords) for lgname & lgpassword
function loginRequest( $logintoken ) {
	global $endPoint;

	$params2 = [
		"action" => "login",
		"lgname" => "bot_user_name",
		"lgpassword" => "bot_password",
		"lgtoken" => $logintoken,
		"format" => "json"
	];

	$ch = curl_init();

	curl_setopt( $ch, CURLOPT_URL, $endPoint );
	curl_setopt( $ch, CURLOPT_POST, true );
	curl_setopt( $ch, CURLOPT_POSTFIELDS, http_build_query( $params2 ) );
	curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
	curl_setopt( $ch, CURLOPT_COOKIEJAR, "cookie.txt" );
	curl_setopt( $ch, CURLOPT_COOKIEFILE, "cookie.txt" );

	$output = curl_exec( $ch );
	curl_close( $ch );

}

// Step 3: GET request to fetch CSRF token
function getCSRFToken() {
	global $endPoint;

	$params3 = [
		"action" => "query",
		"meta" => "tokens",
		"format" => "json"
	];

	$url = $endPoint . "?" . http_build_query( $params3 );

	$ch = curl_init( $url );

	curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
	curl_setopt( $ch, CURLOPT_COOKIEJAR, "cookie.txt" );
	curl_setopt( $ch, CURLOPT_COOKIEFILE, "cookie.txt" );

	$output = curl_exec( $ch );
	curl_close( $ch );

	$result = json_decode( $output, true );
	return $result["query"]["tokens"]["csrftoken"];
}

// Step 4: POST request to upload a file directly
function upload( $csrftoken ) {
	global $endPoint;

	$params4 = [
		"action" => "upload",
		"filename" => "Sandboxfile1.jpg",
		"file" => curl_file_create("localfile.jpg", "image/jpeg", "Sandboxfile1.jpg"),
		"ignorewarnings" => "1",
		"token" => $csrftoken,
		"format" => "json"
	];

	$ch = curl_init();

	curl_setopt( $ch, CURLOPT_URL, $endPoint );
	curl_setopt( $ch, CURLOPT_POST, true );
	curl_setopt( $ch, CURLOPT_HTTPHEADER, array('Content-type: multipart/form-data'));
	curl_setopt( $ch, CURLOPT_POSTFIELDS, $params4 );
	curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
	curl_setopt( $ch, CURLOPT_COOKIEJAR, "cookie.txt" );
	curl_setopt( $ch, CURLOPT_COOKIEFILE, "cookie.txt" );

	$output = curl_exec( $ch );
	curl_close( $ch );

	echo ( $output );
}

JavaScript

/*  
    upload_file_directly.js
 
    MediaWiki API Demos
    Demo of `Upload` module: Sending post request to upload a file directly

    MIT license
*/

var fs = require('fs'),
    request = require('request').defaults({jar: true}),
    url = "https://test.wikipedia.org/w/api.php";

// Step 1: GET request to fetch login token
function getLoginToken() {
    var params_0 = {
        action: "query",
        meta: "tokens",
        type: "login",
        format: "json"
    };

    request.get({ url: url, qs: params_0 }, function (error, res, body) {
        if (error) {
            return;
        }
        var data = JSON.parse(body);
        loginRequest(data.query.tokens.logintoken);
    });
}

// Step 2: POST request to log in. 
// Use of main account for login is not
// supported. Obtain credentials via Special:BotPasswords
// (https://www.mediawiki.org/wiki/Special:BotPasswords) for lgname & lgpassword
function loginRequest(login_token) {
    var params_1 = {
        action: "login",
        lgname: "bot_username",
        lgpassword: "bot_password",
        lgtoken: login_token,
        format: "json"
    };

    request.post({ url: url, form: params_1 }, function (error, res, body) {
        if (error) {
            return;
        }
        getCsrfToken();
    });
}

// Step 3: GET request to fetch CSRF token
function getCsrfToken() {
    var params_2 = {
        action: "query",
        meta: "tokens",
        format: "json"
    };

    request.get({ url: url, qs: params_2 }, function(error, res, body) {
        if (error) {
            return;
        }
        var data = JSON.parse(body);
        upload(data.query.tokens.csrftoken);
    });
}

// Step 4: POST request to upload a file directly
function upload(csrf_token) {
    var params_3 = {
        action: "upload",
        filename: "Sandboxfile1.jpg",
        ignorewarnings: "1",
        token: csrf_token,
        format: "json"
    };

    var file = {
        file: fs.createReadStream('My.jpg')
    };

    var formData = Object.assign( {}, params_3, file );

    request.post({ url: url, formData: formData }, function (error, res, body) {
        body = JSON.parse(body);
        if (error) {
            return;
        }
        else if (body.upload.result === "Success"){
            console.log("File Uploaded :)");
        }
    });
}

// Start From Step 1
getLoginToken();

MediaWiki JS

/*
    upload_file_directly.js
    MediaWiki API Demos
    Demo of `Upload` module: Sending post request to upload a file directly
    MIT license
*/

var param = {
		filename: 'File_1.jpg',
		format: 'json',
		ignorewarnings: 1
	},
	fileInput = $( '<input/>' ).attr( 'type', 'file' ),
	submitBtn = $( '<input/>' ).attr( 'type', 'button' ).attr( 'value', 'Upload' ),
	api = new mw.Api();

$( '#bodyContent' ).append( [ fileInput, submitBtn ] );

$( submitBtn ).on( 'click', function () {
	api.upload( fileInput[ 0 ], param ).done( function ( data ) {
		console.log( data.upload.filename + ' has sucessfully uploaded.' );
	} ).fail( function ( data ) {
		console.log( data );
	} );
} );

示例二:从URL上传文件

这需要 wiki 的本地设置中的 $wgAllowCopyUploads = true 和具有 upload_by_url 用户权限的帐户。

POST请求

响应

结果
{
	"upload": {
		"result": "Success",
		"filename": "New_image.jpg",
		},
		"imageinfo": {
			"userid": 42588,
			"commonmetadata": [],
			"sha1": "0553e6106acdc4d09d9ec5f204aff9e7594193cc",
			"bitdepth": 8,
			"extmetadata": {
				"ObjectName": {
					"source": "mediawiki-metadata",
					"hidden": "",
					"value": "Tempa123"
				},
				"CommonsMetadataExtension": {
					"source": "extension",
					"hidden": "",
					"value": 1.2
				},
				"Categories": {
					"source": "commons-categories",
					"hidden": "",
					"value": ""
				},
				"DateTime": {
					"source": "mediawiki-metadata",
					"hidden": "",
					"value": "2019-03-06 18:24:46"
				},
				"Assessments": {
					"source": "commons-categories",
					"hidden": "",
					"value": ""
				}
			},
			"descriptionshorturl": "https://test.wikipedia.org/w/index.php?curid=0",
			"height": 240,
			"mediatype": "BITMAP",
			"timestamp": "2019-03-06T18:30:53Z",
			"descriptionurl": "https://test.wikipedia.org/wiki/File:New_image.jpg",
			"metadata": [
				{
					"value": 2,
					"name": "MEDIAWIKI_EXIF_VERSION"
				}
			],
			"mime": "image/jpeg",
			"url": "https://upload.wikimedia.org/wikipedia/test/3/34/New_image.jpg",
			"user": "Mansi29ag",
			"width": 320,
			"size": 27202,
			"parsedcomment": "",
			"canonicaltitle": "File:New image.jpg",
			"html": "<p>A file with this name exists already, please check <strong><a class=\"mw-selflink selflink\">File:New image.jpg</a></strong> if you are not sure if you want to change it.\n</p>\n<div class=\"thumb tright\"><div class=\"thumbinner\" style=\"width:182px;\"><a href=\"/w/index.php?title=Special:Upload&amp;wpDestFile=New_image.jpg\" class=\"new\" title=\"File:New image.jpg\">File:New image.jpg</a>  <div class=\"thumbcaption\"></div></div></div>\n",
			"comment": ""
		}
	}
}

示例代码

Python

"""
    upload_file_from_url.py

    MediaWiki API Demos
    Demo of `Upload` module: Post request to upload a file from a URL

    MIT license
"""

import requests

S = requests.Session()
URL = "https://test.wikipedia.org/w/api.php"

# Step 1: Retrieve a login token
PARAMS_1 = {
    "action": "query",
    "meta": "tokens",
    "type": "login",
    "format": "json"
}

R = S.get(url=URL, params=PARAMS_1)
DATA = R.json()

LOGIN_TOKEN = DATA["query"]["tokens"]["logintoken"]

# Step 2: Send a post request to login. Use of main account for login is not
# supported. Obtain credentials via Special:BotPasswords
# (https://www.mediawiki.org/wiki/Special:BotPasswords) for lgname & lgpassword
PARAMS_2 = {
    "action": "login",
    "lgname": "bot_username",
    "lgpassword": "bot_password",
    "format": "json",
    "lgtoken": LOGIN_TOKEN
}

R = S.post(URL, data=PARAMS_2)

# Step 3: While logged in, retrieve a CSRF token
PARAMS_3 = {
    "action": "query",
    "meta":"tokens",
    "format":"json"
}

R = S.get(url=URL, params=PARAMS_3)
DATA = R.json()

CSRF_TOKEN = DATA["query"]["tokens"]["csrftoken"]

# Step 4: Post request to upload a file from a URL
PARAMS_4 = {
    "action": "upload",
    "filename": "new_image.jpg",
    "url": "https://farm9.staticflickr.com/8213/8300206113_374c017fc5.jpg",
    "format": "json",
    "token": CSRF_TOKEN,
    "ignorewarnings": 1
}

R = S.post(URL, data=PARAMS_4)
DATA = R.json()
print(DATA)

PHP

<?php

/*
    upload_file_from_url.php

    MediaWiki API Demos
	Demo of `Upload` module: Post request to upload a file from a URL

    MIT license
*/

$endPoint = "https://test.wikipedia.org/w/api.php";

$login_Token = getLoginToken(); // Step 1
loginRequest( $login_Token ); // Step 2
$csrf_Token = getCSRFToken(); // Step 3
upload( $csrf_Token ); // Step 4

// Step 1: GET request to fetch login token
function getLoginToken() {
	global $endPoint;

	$params1 = [
		"action" => "query",
		"meta" => "tokens",
		"type" => "login",
		"format" => "json"
	];

	$url = $endPoint . "?" . http_build_query( $params1 );

	$ch = curl_init( $url );
	curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
	curl_setopt( $ch, CURLOPT_COOKIEJAR, "cookie.txt" );
	curl_setopt( $ch, CURLOPT_COOKIEFILE, "cookie.txt" );

	$output = curl_exec( $ch );
	curl_close( $ch );

	$result = json_decode( $output, true );
	return $result["query"]["tokens"]["logintoken"];
}

// Step 2: POST request to log in. Use of main account for login is not
// supported. Obtain credentials via Special:BotPasswords
// (https://www.mediawiki.org/wiki/Special:BotPasswords) for lgname & lgpassword
function loginRequest( $logintoken ) {
	global $endPoint;

	$params2 = [
		"action" => "login",
		"lgname" => "bot_user_name",
		"lgpassword" => "bot_password",
		"lgtoken" => $logintoken,
		"format" => "json"
	];

	$ch = curl_init();

	curl_setopt( $ch, CURLOPT_URL, $endPoint );
	curl_setopt( $ch, CURLOPT_POST, true );
	curl_setopt( $ch, CURLOPT_POSTFIELDS, http_build_query( $params2 ) );
	curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
	curl_setopt( $ch, CURLOPT_COOKIEJAR, "cookie.txt" );
	curl_setopt( $ch, CURLOPT_COOKIEFILE, "cookie.txt" );

	$output = curl_exec( $ch );
	curl_close( $ch );

}

// Step 3: GET request to fetch CSRF token
function getCSRFToken() {
	global $endPoint;

	$params3 = [
		"action" => "query",
		"meta" => "tokens",
		"format" => "json"
	];

	$url = $endPoint . "?" . http_build_query( $params3 );

	$ch = curl_init( $url );

	curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
	curl_setopt( $ch, CURLOPT_COOKIEJAR, "cookie.txt" );
	curl_setopt( $ch, CURLOPT_COOKIEFILE, "cookie.txt" );

	$output = curl_exec( $ch );
	curl_close( $ch );

	$result = json_decode( $output, true );
	return $result["query"]["tokens"]["csrftoken"];
}

// Step 4: POST request to upload a file from a URL
function upload( $csrftoken ) {
	global $endPoint;

	$params4 = [
		"action" => "upload",
		"filename" => "Test-Jayprakash12345.jpg",
		"url" => "https://farm9.staticflickr.com/8213/8300206113_374c017fc5.jpg",
		"ignorewarnings" => "1",
		"token" => $csrftoken,
		"format" => "json"
	];

	$ch = curl_init();

	curl_setopt( $ch, CURLOPT_URL, $endPoint );
	curl_setopt( $ch, CURLOPT_POST, true );
	curl_setopt( $ch, CURLOPT_POSTFIELDS, http_build_query( $params4 ) );
	curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
	curl_setopt( $ch, CURLOPT_COOKIEJAR, "cookie.txt" );
	curl_setopt( $ch, CURLOPT_COOKIEFILE, "cookie.txt" );

	$output = curl_exec( $ch );
	curl_close( $ch );

	echo ( $output );
}

JavaScript

/*  
    upload_file_from_url.js
 
    MediaWiki API Demos
    Demo of `Upload` module: Post request to upload a file from a URL

    MIT license
*/

var request = require('request').defaults({jar: true}),
    url = "https://test.wikipedia.org/w/api.php";

// Step 1: GET request to fetch login token
function getLoginToken() {
    var params_0 = {
        action: "query",
        meta: "tokens",
        type: "login",
        format: "json"
    };

    request.get({ url: url, qs: params_0 }, function (error, res, body) {
        if (error) {
            return;
        }
        var data = JSON.parse(body);
        loginRequest(data.query.tokens.logintoken);
    });
}

// Step 2: POST request to log in. 
// Use of main account for login is not
// supported. Obtain credentials via Special:BotPasswords
// (https://www.mediawiki.org/wiki/Special:BotPasswords) for lgname & lgpassword
function loginRequest(login_token) {
    var params_1 = {
        action: "login",
        lgname: "bot_username",
        lgpassword: "bot_password",
        lgtoken: login_token,
        format: "json"
    };

    request.post({ url: url, form: params_1 }, function (error, res, body) {
        if (error) {
            return;
        }
        getCsrfToken();
    });
}

// Step 3: GET request to fetch CSRF token
function getCsrfToken() {
    var params_2 = {
        action: "query",
        meta: "tokens",
        format: "json"
    };

    request.get({ url: url, qs: params_2 }, function(error, res, body) {
        if (error) {
            return;
        }
        var data = JSON.parse(body);
        editRequest(data.query.tokens.csrftoken);
    });
}

// Step 4: POST request to upload a file from a URL
function editRequest(csrf_token) {
    var params_3 = {
        action: "upload",
        filename: "Test-ABCD.jpg",
        url: "https://farm9.staticflickr.com/8213/8300206113_374c017fc5.jpg",
        ignorewarnings: "1",
        token: csrf_token,
        format: "json"
    };

    request.post({ url: url, form: params_3 }, function (error, res, body) {
        if (error) {
            return;
        }
        console.log(body);
    });
}

// Start From Step 1
getLoginToken();

MediaWiki JS

/*
	upload_file_from_url.js

	MediaWiki API Demos
	Demo of `Upload` module: Post request to upload a file from a URL

	MIT License
*/

var params = {
		action: 'upload',
		filename: 'New_image.jpg',
		url: 'https://farm9.staticflickr.com/8213/8300206113_374c017fc5.jpg',
		ignorewarnings: '1',
		format: 'json'
	},
	api = new mw.Api();

api.postWithToken( 'csrf', params ).done( function ( data ) {
	console.log( data );
} );

示例三:分块上传文件

由于在单个POST请求中上传大文件可能不可靠,因此 API 还支持分块上传模式,您可以使用文件的多部分发出多个请求。 这在 MediaWiki 1.20 及更高版本中可用,尽管在 1.25 版本之前,SVG文件无法通过分块上传上传。 这在支持 FileAPI 的浏览器中由 Extension:上传向导 使用,以1MB的块上传文件,但您可以选择自己的大小。 这与stash模式结合使用,将文件分段构建,然后在最后提交。

第一步:发送第一个块中的内容

对于除最后一个块之外的所有块,您将收到以下信息:

结果1
{
	"upload": {
		"offset": 5000,
		"result": "Continue",
		"filekey": "16gqn54g1z98.4g5brp.42588.jpg"
	}
}

第二步:为第二个以及更多块传递参数filekey

您还将从之前的 continue 结果中获得参数filekey

对最后一个块,您将接收到:

结果2
{
	"upload": {
		"filekey": "16gqn663shqw.pop712.42588.jpg",
		"imageinfo": {
			"mediatype": "UNKNOWN",
			"user": "None",
			"comment": "None",
			"height": 600,
			"size": 48316,
			"descriptionurl": "https://test.wikipedia.org/wiki/Special:UploadStash/file/16gqn663shqw.pop712.42588.jpg",
			"html": "<p>A file with this name exists already, please check <strong><a class=\"mw-selflink selflink\">File:20190314182304!chunkedupload 4a2a524b5147.jpg</a></strong> if you are not sure if you want to change it.\n</p>\n<div class=\"thumb tright\"><div class=\"thumbinner\" style=\"width:182px;\"><a href=\"/w/index.php?title=Special:Upload&amp;wpDestFile=20190314182304!chunkedupload_4a2a524b5147.jpg\" class=\"new\" title=\"File:20190314182304!chunkedupload 4a2a524b5147.jpg\">File:20190314182304!chunkedupload 4a2a524b5147.jpg</a>  <div class=\"thumbcaption\"></div></div></div>\n",
			"canonicaltitle": "File:20190314182304!chunkedupload 4a2a524b5147.jpg",
			"extmetadata": {
				"DateTime": {
					"source": "mediawiki-metadata",
					"hidden": "",
					"value": "2019-03-14 18:08:10"
				},
				"CommonsMetadataExtension": {
					"source": "extension",
					"hidden": "",
					"value": 1.2
				},
				"Assessments": {
					"source": "commons-categories",
					"hidden": "",
					"value": ""
				},
				"Categories": {
					"source": "commons-categories",
					"hidden": "",
					"value": ""
				},
				"ObjectName": {
					"source": "mediawiki-metadata",
					"hidden": "",
					"value": "20190314180809!chunkedupload 6d04724f88bd"
				}
			},
			"commonmetadata": [
				{
					"value": "371DB9CF4042631EC8B5E9963CA5AC16",
					"name": "OriginalDocumentID"
				},
				{
					"value": "Adobe Photoshop CC 2015 Windows",
					"name": "Software"
				}
			],
			"anon": "",
			"timestamp": "2019-03-14T18:23:05Z",
			"bitdepth": 8,
			"mime": "image/jpeg",
			"sha1": "d07dbfcb97861b23fbe6b33efb14856694458450",
			"url": "https://test.wikipedia.org/wiki/Special:UploadStash/file/16gqn663shqw.pop712.42588.jpg",
			"parsedcomment": "",
			"userid": "None",
			"metadata": [
				{
					"value": "371DB9CF4042631EC8B5E9963CA5AC16",
					"name": "OriginalDocumentID"
				},
				{
					"value": "Adobe Photoshop CC 2015 Windows",
					"name": "Software"
				},
				{
					"value": 2,
					"name": "MEDIAWIKI_EXIF_VERSION"
				}
			],
			"width": 600
		},
		"result": "Success"
	}
}

第三步:使用 filekey 将上传提交到存储区之外的最终上传

最终上传的结果将包括完整、准确的对象imageinfo,这与您从非分块上传获得的结果一致。

结果3
{
	"upload": {
		"imageinfo": {
			"mediatype": "BITMAP",
			"user": "Mansi29ag",
			"comment": "Upload Testing",
			"height": 600,
			"size": 48316,
			"descriptionurl": "https://test.wikipedia.org/wiki/File:Testfile5.jpg",
			"html": "<p>A file with this name exists already, please check <strong><a class=\"mw-selflink selflink\">File:Testfile5.jpg</a></strong> if you are not sure if you want to change it.\n</p>\n<div class=\"thumb tright\"><div class=\"thumbinner\" style=\"width:182px;\"><a href=\"/w/index.php?title=Special:Upload&amp;wpDestFile=Testfile5.jpg\" class=\"new\" title=\"File:Testfile5.jpg\">File:Testfile5.jpg</a>  <div class=\"thumbcaption\"></div></div></div>\n",
			"canonicaltitle": "File:Testfile5.jpg",
			"extmetadata": {
				"DateTime": {
					"source": "mediawiki-metadata",
					"hidden": "",
					"value": "2019-03-14 18:08:10"
				},
				"CommonsMetadataExtension": {
					"source": "extension",
					"hidden": "",
					"value": 1.2
				},
				"Assessments": {
					"source": "commons-categories",
					"hidden": "",
					"value": ""
				},
				"Categories": {
					"source": "commons-categories",
					"hidden": "",
					"value": ""
				},
				"ObjectName": {
					"source": "mediawiki-metadata",
					"hidden": "",
					"value": "20190314180809!chunkedupload 6d04724f88bd"
				}
			},
			"commonmetadata": [
				{
					"value": "371DB9CF4042631EC8B5E9963CA5AC16",
					"name": "OriginalDocumentID"
				},
				{
					"value": "Adobe Photoshop CC 2015 Windows",
					"name": "Software"
				}
			],
			"sha1": "d07dbfcb97861b23fbe6b33efb14856694458450",
			"width": 600,
			"bitdepth": 8,
			"mime": "image/jpeg",
			"url": "https://upload.wikimedia.org/wikipedia/test/8/8e/Testfile5.jpg",
			"parsedcomment": "Upload Testing",
			"descriptionshorturl": "https://test.wikipedia.org/w/index.php?curid=0",
			"userid": 42588,
			"metadata": [
				{
					"value": "371DB9CF4042631EC8B5E9963CA5AC16",
					"name": "OriginalDocumentID"
				},
				{
					"value": "Adobe Photoshop CC 2015 Windows",
					"name": "Software"
				},
				{
					"value": 2,
					"name": "MEDIAWIKI_EXIF_VERSION"
				}
			],
			"timestamp": "2019-03-14T18:23:07Z"
		},
		"result": "Success",
		"filename": "Testfile5.jpg"
	}
}

示例代码

Python

"""
    upload_file_in_chunks.py

    MediaWiki API Demos
    Demo of `Upload` module: Step-by-step process to upload a file in chunks

    MIT license
"""

import os
import requests

S = requests.Session()
URL = "https://test.wikipedia.org/w/api.php"

# File path of the image to be uploaded
FILE_PATH = 'f.jpg'
FILE = open(FILE_PATH, 'rb')
FILE_SIZE = os.stat(FILE_PATH).st_size

# Bot credentials
BOT_USERNAME = 'enter_a_bot_username'
BOT_PASSWORD = 'enter_a_bot_password'

def read_chunks(file_object, chunk_size=5000):
    """Return the next chunk of the file"""

    while True:
        data = file_object.read(chunk_size)
        if not data:
            break
        yield data

def fetch_login_token():
    """Retrieve a login token"""

    params = {
        "action": "query",
        "meta": "tokens",
        "type": "login",
        "format": "json"
    }
    res = S.get(url=URL, params=params)
    data = res.json()
    return data["query"]["tokens"]["logintoken"]

def user_login(login_token, username, password):
    """Send a post request to login
    Use of main account for login is not supported. Obtain credentials via
    Special:BotPasswords (https://www.mediawiki.org/wiki/Special:BotPasswords)
    for lgname & lgpassword """

    params = {
        "action": "login",
        "lgname": username,
        "lgpassword": password,
        "format": "json",
        "lgtoken": login_token
    }
    S.post(URL, data=params)

def fetch_csrf_token():
    """While logged in, retrieve a CSRF token"""

    params = {
        "action": "query",
        "meta":"tokens",
        "format":"json"
    }
    res = S.get(url=URL, params=params)
    data = res.json()
    return data["query"]["tokens"]["csrftoken"]

def upload_file_in_chunks(csrf_token):
    """Send multiple post requests to upload a file in chunks using `stash` mode.
    Stash mode is used to build a file up in pieces and then commit it at the end
    """

    chunks = read_chunks(FILE)
    chunk = next(chunks)

    # Parameters for the first chunk
    params = {
        "action": "upload",
        "stash": 1,
        "filename": "chunk_test.jpg",
        "filesize": FILE_SIZE,
        "offset": 0,
        "format": "json",
        "token": csrf_token,
        "ignorewarnings": 1
    }
    index = 0
    file = {'chunk':('{}.jpg'.format(index), chunk, 'multipart/form-data')}
    index += 1
    res = S.post(URL, files=file, data=params)
    data = res.json()

    # Pass the filekey parameter for second and further chunks
    for chunk in chunks:
        params = {
            "action": "upload",
            "stash": 1,
            "offset": data["upload"]["offset"],
            "filename": "chunk_test.jpg",
            "filesize": FILE_SIZE,
            "filekey": data["upload"]["filekey"],
            "format": "json",
            "token": csrf_token,
            "ignorewarnings": 1
        }
        file = {'chunk':('{}.jpg'.format(index), chunk, 'multipart/form-data')}
        index += 1
        res = S.post(URL, files=file, data=params)
        data = res.json()

    # Final upload using the filekey to commit the upload out of the stash area
    params = {
        "action": "upload",
        "filename": "chunk_test.jpg",
        "filekey": data["upload"]["filekey"],
        "format": "json",
        "comment": "Upload Testing",
        "token": csrf_token,
    }
    res = S.post(URL, data=params)
    data = res.json()

def main():
    """ Four-step process to uploading a file in chunks"""

    login_token = fetch_login_token() # Step 1: Fetch login token
    user_login(login_token, BOT_USERNAME, BOT_PASSWORD) # Step 2: Login
    csrf_token = fetch_csrf_token() # Step 3: Fetch CSRF token
    upload_file_in_chunks(csrf_token) # Step 3: Upload a file in chunks

if __name__ == "__main__":
    main()

JavaScript

/*  
    upload_file_in_chunks.js
 
    MediaWiki API Demos
    Demo of `Upload` module: Step-by-step process to upload a file in chunks

    MIT license
*/

var fs = require('fs'),
    request = require('request').defaults({jar: true}),
    url = "http://dev.wiki.local.wmftest.net:8080/w/api.php",
    filename = "My.jpg";

// Step 1: GET request to fetch login token
function getLoginToken() {
    var params_0 = {
        action: "query",
        meta: "tokens",
        type: "login",
        format: "json"
    };

    request.get({ url: url, qs: params_0 }, function (error, res, body) {
        if (error) {
            return;
        }
        var data = JSON.parse(body);
        loginRequest(data.query.tokens.logintoken);
    });
}

// Step 2: POST request to log in. 
// Use of main account for login is not
// supported. Obtain credentials via Special:BotPasswords
// (https://www.mediawiki.org/wiki/Special:BotPasswords) for lgname & lgpassword
function loginRequest(login_token) {
    var params_1 = {
        action: "login",
        lgname: "bot_username",
        lgpassword: "bot_password",
        lgtoken: login_token,
        format: "json"
    };

    request.post({ url: url, form: params_1 }, function (error, res, body) {
        if (error) {
            return;
        }
        getCsrfToken();
    });
}

// Step 3: GET request to fetch CSRF token
function getCsrfToken() {
    var params_2 = {
        action: "query",
        meta: "tokens",
        format: "json"
    };

    request.get({ url: url, qs: params_2 }, function(error, res, body) {
        if (error) {
            return;
        }
        var data = JSON.parse(body);
        upload(data.query.tokens.csrftoken);
    });
}

// Step 4: POST request to upload a file
function upload(csrf_token) {
    /*
        Send multiple post requests to upload a file in chunks using `stash` mode.
        Stash mode is used to build a file up in pieces and then commit it at the end
    */
    var fileSizeInBytes = fs.statSync(filename).size;
    var headers = {
        "Content-Type": "multipart/form-data"
    };

    var params_3 = {
        action: "upload",
        stash: "1",
        filename: "Sandboxfile1.jpg",
        filesize: fileSizeInBytes,
        offset: "0",
        ignorewarnings: "1",
        token: csrf_token,
        format: "json"
    };

    var file = {
        file: fs.createReadStream(filename)
    };

    var formData = Object.assign( {}, params_3, file );

    request.post({ url: url, headers: headers, formData: formData }, function (error, res, body) {
        body = JSON.parse(body);
        if (error) {
            return;
        }

        params_4 = {
            action: "upload",
            filename: "Sandboxfile1.jpg",
            filekey: body.upload.filekey,
            comment: "Upload Testing",
            token: csrf_token,
            format: "json"
        };

        request.post({ url: url, form: params_4 }, function (error, res, body) {
            body = JSON.parse(body);
            if (error) {
                return;
            }
            console.log(body.upload.result);
        });
    });
}

// Start From Step 1
getLoginToken();

MediaWiki JS

/*
    upload_file_in_chunks.js
    MediaWiki API Demos
    Demo of `Upload` module: Step-by-step process to upload a file in chunks
    MIT license
*/

var param = {
		filename: 'TestFile_2.jpg',
		format: 'json',
		ignorewarnings: 1
	},
	fileInput = $( '<input/>' ).attr( 'type', 'file' ),
	submitBtn = $( '<input/>' ).attr( 'type', 'button' ).attr( 'value', 'Upload' ),
	api = new mw.Api();

$( '#bodyContent' ).append( [ fileInput, submitBtn ] );

$( submitBtn ).on( 'click', function () {
	api.uploadToStash( fileInput[ 0 ], param ).done( function ( finish ) {
		finish( param ).done( function ( data ) {
			console.log( data.upload.filename + ' has sucessfully uploaded.' );
		} ).fail( function ( data ) {
			console.log( data );
		} );
	} );
} );

可能的错误

代码 信息
mustbeloggedin 您必须登录才能上传本文件。
permissiondenied 您所处的用户组 没有upload权限。
fileexists-shared-forbidden 共享文件库中已有以此命名的文件。
chunk-too-small 对于非最终块,最小块大小为n字节。
stashfailed 文件未通过验证。
verification-error 数据损坏或文件扩展名不与MIME类型一致。
windows-nonascii-filename 服务器不支持包含特殊字符的文件名。
copyuploaddisabled 已禁用URL上传。

另请参阅上面关于 #Upload warnings 的部分。

参数历史

  • v1.21: 启用async checkstatus
  • v1.19: 启用offset filesize chunk
  • v1.18: 启用stash filekey
  • v1.17: 启用stash, statuskey, leavemessage, asyncdownload
  • v1.18: 弃用sessionkey
  • v1.17: 弃用watch

补充资料

  • 若要检查正在上传到stash的状态或从stash发布的文件的进度,则应当使用POST请求:
结果
{
	"upload": {
		"stage": "uploading",
		"offset": 5000,
		"result": "Continue"
	}
}
  • 以下是一个multipart POST/api.php?action=upload的示例,它展示了单个块是如何工作的。 请注意,一旦您成功上传了所有块,您必须取消存储文件以使其出现在 Wiki 中。
扩展內容
User-Agent: <YOUR USER-AGENT>
Content-Type: multipart/form-data; boundary=--24b7c3bb-fb4d-45c3-937c-11c2e0c2525b
Host: commons.wikimedia.org
Cookie: <cookies>
Connection: Keep-Alive

--24b7c3bb-fb4d-45c3-937c-11c2e0c2525b
Content-Disposition: form-data; name="filename"
Content-Length: 20

UploadTest356456.png
--24b7c3bb-fb4d-45c3-937c-11c2e0c2525b
Content-Disposition: form-data; name="offset"
Content-Length: 1

0
--24b7c3bb-fb4d-45c3-937c-11c2e0c2525b
Content-Disposition: form-data; name="format"
Content-Length: 4

json
--24b7c3bb-fb4d-45c3-937c-11c2e0c2525b
Content-Disposition: form-data; name="ignorewarnings"
Content-Length: 1

1
--24b7c3bb-fb4d-45c3-937c-11c2e0c2525b
Content-Disposition: form-data; name="filesize"
Content-Length: 3

971
--24b7c3bb-fb4d-45c3-937c-11c2e0c2525b
Content-Disposition: form-data; name="token"
Content-Length: 42

<YOUR_CSRF_TOKEN_HERE>
--24b7c3bb-fb4d-45c3-937c-11c2e0c2525b
Content-Disposition: form-data; name="stash"
Content-Length: 1

1
--24b7c3bb-fb4d-45c3-937c-11c2e0c2525b
Content-Disposition: form-data; name="chunk"; filename="1.png"
Content-Type: application/octet-stream
Content-Length: 971

<RAW_BYTES_FROM_FILE_HERE>
--24b7c3bb-fb4d-45c3-937c-11c2e0c2525b--

參見