API talk:Upload

From mediawiki.org
Latest comment: 5 months ago by Arsenii Gorkin in topic Upload duplicate

Flag: Don't overwrite existing file[edit]

It would be nice if there was a flag that said: Don't overwrite any already existing file. This could help in preventing errors in bots, especially as Special:Upload mangles the filename a bit, so it's not entirely trivial to make sure a file of a given name does not already exist. --Tbleher 20:20, 14 February 2008 (UTC)Reply

Good one. I'll keep this in mind. --Catrope 21:32, 17 February 2008 (UTC)Reply

File Contents?[edit]

Could you be more specific on the file contents? Is it just a bunch of bytes, UUEncoded, HEX, or what?

Assuming you mean direct upload, the file content should be sent as part of the request in multipart/form-data format, so essentially yes, just a bunch of bytes. Gurch 05:03, 30 October 2009 (UTC)Reply

I'm trying to do this with curl, but am having no luck with any kind of file content inclusion. Can you give an example? Here are some things I'm trying:

curl -b cookies.txt -d "action=upload&filename=exported.xml&file=$(cat exported.xml)&format=xml&token=$UPLOADTOKEN" http://lookipedia.net/w/api.php

curl -b cookies.txt -d "action=upload&filename=exported.xml&file=<xml>text</xml>&format=xml&token=$UPLOADTOKEN" http://lookipedia.net/w/api.php

curl -b cookies.txt -d "action=upload&filename=exported.xml&file=TEST&format=xml&token=$UPLOADTOKEN" http://lookipedia.net/w/api.php

curl -b cookies.txt -d "action=upload&filename=exported.xml&file=@exported.xml&format=xml&token=$UPLOADTOKEN" http://lookipedia.net/w/api.php

In all cases I get this error:

<error code="missingparam" info="One of the parameters sessionkey, file, url, statuskey is required"/>

Pjrich 17:48, 10 October 2011 (UTC)Reply

Upload by URL[edit]

I'm not having much more luck than you with uploading by URL. I did try retrieving httpstatus using the session key, and got the following result:

{u'upload': {u'content_length': u'5706', u'loaded': 5706, u'upload_session_key': u'12345'}}

But the file wasn't actually uploaded, and I don't see any way of determining what went wrong. --R'n'B 18:45, 29 October 2009 (UTC)Reply

It was broken before, was fixed in r58337 -- Gurch 05:11, 30 October 2009 (UTC)Reply

badtoken[edit]

my script for accessing my mediawiki works with edits, moves and deletes. upload does not work - i get a badtoken response:

/api/error/@code=badtoken
/api/error/@info=Invalid token

The doc says the token should be requested with prop=info, while regular edit tokens that i use have prop=info|revisions. The titles param given in the api doc is Foo which is not helpful - what is the title to be used? It would be great to have a full working example. -- Seppl2013 (talk) 08:52, 28 August 2013 (UTC)Reply

Unrecognized value for parameter action: upload[edit]

I'm trying to upload a file via wget. Login and fetching token is OK, but on upload...

wget --load-cookies cookies.txt -O upload.xml \
 --post-data "action=upload&filename=atlasmw-export.xml&file=[content goes here]&token=$EDITTOKEN" \
 $API

I get this:

<error code="unknown_action" info="Unrecognized value for parameter &#039;action&#039;: upload" xml:space="preserve">


Documentation says:

api.php ? action=upload & filename=Test.txt & file=file_contents_here & token=+\

What's wrong? Using MediaWiki 1.15.1. Jpatokal 03:32, 20 November 2009 (UTC)Reply

It's a 1.16 feature. Max Semenik 05:45, 20 November 2009 (UTC)Reply

overwrite: text parameter ignored[edit]

is there a good reason the text parameter is ignored when overwriting an existing file? imho it would make sense to overwrite the description, too. -- 23:55, 23 April 2010 (UTC)Reply

Mediawiki Push Extension[edit]

Is anyone here familiar with the MW Push extension?

Trying to get it to work and not having much success.

The extension author has been less than helpful:

"In any case, I don't know what your issue is, so can't really help you any further."

I keep getting the same error:

Could not obtain an edit token on the target wiki

After reading and reading I suspect it might have something to do with the API Upload.

Any thoughts?


I had the same problem, it was something to do with my target media wiki installation, I re-installed a clean version (version 1.19.2) and it worked for me. This is a little vague sorry but perhaps that might help you if it isn't too much to do that, certainly something to try if you don't have any better options.

--Cgeroux (talk) 16:54, 15 October 2012 (UTC)Reply

I'm not sure if this is the place to ask but I can only find one mention of the where the WikiMedia API can do a push. I'd like to know if you can get wikipedia to push a API request to a client to trigger an action? If so can you direct me to the API document(s) that discusses this?

--lukejmorrison (talk) 13:34, 2 June 2014 (EST New York)

Reverting to an earlier revision?[edit]

I'm not sure if this is the right place, but: Does anyone know if it's possible to revert to an earlier revision? A workaround using archived image URLs comes to mind, but the particular wiki has URL uploads disabled. --84.186.216.128 00:07, 24 February 2012 (UTC)Reply

Async uploads[edit]

After digging through the code to find that wgAllowAsyncCopyUploads iswas the correct parameter to allow an async upload, I now get the following error back:

Asynchronous copy uploads are no longer possible as of r81612

Is there any plan to re-introduce this option? --Brian McNeil (talk) 12:13, 18 September 2012 (UTC)Reply

Real World Examples[edit]

Although not an API example, the Html2Wiki extension invokes the internal methods for uploading a file in it's saveImage() method.

from https://git.wikimedia.org/blob/mediawiki%2Fextensions%2FHtml2Wiki/HEAD/specials%2FSpecialHtml2Wiki.php

$title = $this->makeTitle( NS_FILE );
$image = wfLocalFile( $title );            
$result = $image->upload($tmpFile, $comment, $pageText);

Is there any real world example out there (as for the login API) how to use the upload API correctly? This could help many peoples. --Steviex2 (talk) 22:08, 7 February 2013 (UTC)Reply

Real-world examples include:
  • Extension:UploadWizard (JavaScript using XHR)
  • Apps/Commons (Java and Objective-C implementations)
  • Wiki Loves Monuments app from last year[1] (JavaScript using PhoneGap FileTransfer API)
--brion (talk) 01:02, 8 February 2013 (UTC)Reply


...And Mobile Frontend. They are all big projects which I checked. What I really mean is a simple, basic code snipped like for the Login-API. The extensions are way too big to simply adapt it for own projects. Uploading into MediaWiki is a core feature which should be documented as well as the Login-API for developers.

Since more and more people are coding in PHP and JQuery, I would be happy to see simple examples to use the Upload-API with this languages. This should be a small step for a professional MW-dev but a big step for the community :-).

PS: I can't understand why the internet is full of misunderstandings and time consuming trial and errors about this topic, while the original developers should know this few lines of code in every provided language very well. I also would appreciate informations wether we are talking about a file stream or a representation on disk. For example could we use $_FILES['userfile']['temp_name'] and or file_get_contents(). What would be a complete CURL-Realisation? Is the same possible with JQuery? What about the "same origin policy" in this context?

--Steviex2 (talk) 01:44, 8 February 2013 (UTC)Reply

I'll see about whipping up some PHP and JS examples... In the meantime, the thing to know about cross-origin policy is that you probably won't be able to make a successful authenticated POST request to the API from JavaScript on another domain unless it's on the short whitelist of Wikimedia sites. That is, you could upload a file to Commons from a gadget on Wikipedia, but not from an arbitrary web site. but if you route through your server, your PHP code can certainly do it. -- brion (talk) 16:30, 8 February 2013 (UTC)Reply

Aha this is a very important point for people having more then one Wiki-installs and want to exchange files accross different domains. To choose the wrong tech here, could easily result in hours- may be days of useless efforts :-).

Note that for your own wiki installs, you can customize $wgCrossSiteAJAXdomains to whitelist more sites. --brion (talk) 21:08, 8 February 2013 (UTC)Reply

Okay this makes sense now. Yesterday I was wondering when I made a little external login page for my Wikis- thank you. For the Upload-API I would prefer the CURL-way like many others too. By the way in general what about this XML-chunks in the API-Documentation? How would they be used? Is it only an abstraction to reflect the different programming languages, or can we use them in PHP too?

  • Example results we can get with good PHP-knowledge but less propper documentation level :-)
    • One of the parameters filekey, file, url, statuskey is required
    • post request failed The requested URL returned error: 41422
    • request failed: URI too long (longer than 8190)
    • The parameters url, filekey, statuskey can not be used together
    • Invalid Content-Length
    • No upload module set

...after many many hours of trial and errors...still can't get it working with PHP-CURL while successfully login, getting the right edit token etc..

PS: Some remarkable behaviors:

  • The error "One of the parameters filekey, file, url, statuskey is required" is fired even we specify a file-parameter in the url may be because "file" is double checked against class WebRequestUpload which implies uploads can not simulated with CURL, the api needs server var "$_FILES['filename']" and therefor a real form upload which could lead to some serious confusions without mentioning it. ;-)
  • If we put file contents into the url this mostly exceeds the allowed length of an url. I can't believe that this is meant to be the standard way. I think in "PHP-CURL" param file in the url-notation is more a string then real "File contents".

Update: After two days of trial and error, investigations, code reviewing etc. I got it working. I will need another day to clean up and fine tune...I guess this could be mutch easier with a better documentation level.

PS: Anyway...I would like to see the promised code samples (for example JQuery) and will happily assist- If someone has the same problems.

--Steviex2 (talk) 22:37, 8 February 2013 (UTC)Reply

I am having similar problems with PHP implementations, is it possible for you to share the code for this?

--Nischayn22 (talk) 08:11, 4 May 2013 (UTC) What about an example for calling the api internally(like edit)Reply

           $api = new ApiMain(
               new DerivativeRequest(
                   $wgRequest,
                   array(
                       'action'     => 'upload',
                       'file'       => 'blub',
                       'filename'   => 'bla',
                       'url'        => '',
                       'token'      => $_POST["token"]
                   ),
                   false // was posted?
               ),
               true // enable write?
           );
           $api->execute();
Does this work? I did not get internal API to work for uploads. --Osnard (talk) 07:47, 19 December 2014 (UTC)Reply

Seems like the url-parameter is needed otherwise i get "One of the parameters filekey, file, url, statuskey is required" message. What is needed for the url-parameter?
--Michael MPI (talk) 08:08, 13 March 2013 (UTC)Reply

Javascript/jQuery[edit]

Working, rather minimal example using HTML5 APIs and jQuery

function handleFileSelect(evt) {
	var file = evt.target.files[0]; // get (first) File 
	var fileName = evt.target.files[0].name;

	doApiCall(file, fileName);

}

function doApiCall(fileToUpload,fileName){

formdata = new FormData(); //see https://developer.mozilla.org/en-US/docs/Web/Guide/Using_FormData_Objects?redirectlocale=en-US&redirectslug=Web%2FAPI%2FFormData%2FUsing_FormData_Objects
formdata.append("action", "upload");
formdata.append("filename", fileName);
formdata.append("token", mw.user.tokens.get( 'editToken' ) );
formdata.append("file", fileToUpload);

//as we now have created the data to send, we send it...
$.ajax( { //http://stackoverflow.com/questions/6974684/how-to-send-formdata-objects-with-ajax-requests-in-jquery
		url: mw.util.wikiScript( 'api' ), //url to api.php 
		contentType:false,
		processData:false,
		type:'POST',
		data: formdata,//the formdata object we created above
		success:function(data){
		 	//do what you like, console logs are just for demonstration :-)
			console.log("success!");
			console.log(data);
		},
		error:function(xhr,status, error){
			console.log(error)
		}
	});
}

document.getElementById('files').addEventListener('change', handleFileSelect, false); //is a <input type="file" id="files" name="files[]" multiple />

my thanks to the api mailinglist and Steviex2 --Simulo (talk) 15:03, 2 June 2013 (UTC)Reply

Python with requests[edit]

The following should work with Python's requests module:

# The following code is PD-self & CC-zero
import requests

api_url = 'https://project/w/api.php'

USER,PASS=u'BotUsername@Instancename',u'[[Special:BotPasswords]] password' 
#Ensure bot instance is permissioned for createeditmovepage, uploadfile, uploadeditmovefile

FILENAME='/path/to/file'
REMOTENAME='remote_filename.ext'
USER_AGENT='Descriptive User Agent per [[:meta:User-Agent_policy]]'

# get login token and log in
payload = {'action': 'query', 'format': 'json', 'utf8': '', 
           'meta': 'tokens', 'type': 'login'}

r1 = requests.post(api_url, data=payload)
login_token=r1.json()['query']['tokens']['logintoken']

login_payload = {'action': 'login', 'format': 'json', 'utf8': '', 
           'lgname': USER, 'lgpassword': PASS, 'lgtoken': login_token}

r2 = requests.post(api_url, data=login_payload, cookies=r1.cookies)
cookies=r2.cookies.copy()

# We have now logged in and can request edit tokens thusly:

def get_edit_token(cookies):
        edit_token_response=requests.post(api_url, data={'action': 'query',
                                                    'format': 'json', 
                                                    'meta': 'tokens'}, cookies=cookies)
        return edit_token_response.json()['query']['tokens']['csrftoken']

# Now actually perform the upload:

upload_payload={'action': 'upload', 
            'format':'json',
            'filename':REMOTENAME, 
            'comment':'<MY UPLOAD COMMENT>',
            'text':'Text on the File: page... description, license, etc.',
            'token':get_edit_token(cookies)}

files={'file': (REMOTENAME, open(FILENAME,'rb'))}

headers={'User-Agent': USER_AGENT}

upload_response=requests.post(api_url, data=upload_payload,files=files,cookies=cookies,headers=headers)

Hopefully it can save others time and headaches. Storkk (talk) 13:58, 8 December 2016 (UTC)Reply

Filetype mime mismatch[edit]

Hi, I'm trying to upload an image with a multipart/form-data request, however I keep getting told that the file type isn't the same, whereas I am sure that it is. This is what I am sending to api.php:

-----------------------------8d02f9ba3ddf82b
Content-Disposition: form-data; name="action"

upload
-----------------------------8d02f9ba3ddf82b
Content-Disposition: form-data; name="filename"

150px-6025526.png
-----------------------------8d02f9ba3ddf82b
Content-Disposition: form-data; name="token"

XXXXXXXXXXXXXXXXXXXXXXXX+\
-----------------------------8d02f9ba3ddf82b
Content-Disposition: form-data; name="format"

json
-----------------------------8d02f9ba3ddf82b
Content-Disposition: form-data; name="file"; filename="150px-6025526.png"
Content-Type: image/png

<IMAGE DATA HERE>
-----------------------------8d02f9ba3ddf82b--

I cannot find the reason why I am being told the file type doesn't match. Any help would be greatly appreciated. CASIO F-91W (talk) 22:50, 4 June 2013 (UTC)Reply

Real world example with PHP[edit]

As It took some time for me to figure out how to upload file with API, and I'm not alone, I'm providing my example.

This is just example for one to get a clue, it does work, but is far from being tidy, secure, universal, best possible method, able to process warnings, etc..

function uploadFile($localfilename, $filename, $comment, $text, $token, $cookies) {
	
	$handle = fopen($localfilename, "rb");
	$file_body = fread($handle, filesize($localfilename));
	fclose($handle);	
		
	$destination = "http://hy.wikisource.org/w/api.php";	 
	$eol = "\r\n";
	$data = '';
	$header = ''; 
	$mime_boundary=md5(time());
	
	$params = array ('action'=>'upload',
					'filename'=>$filename,
					'text'=>$text,
					'comment'=>$comment,
					//'ignorewarnings'=>'yes', //if uncommented will ignore warnings and will overwrite existing files. Think twice.
					'token'=>$token,
					'format'=>'xml');	
	//parameters 	
	foreach ($params as $key=>$value){
			$data .= '--' . $mime_boundary . $eol;
			$data .= 'Content-Disposition: form-data; name="' . $key . '"' . $eol;
			$data .= 'Content-Type: text/plain; charset=UTF-8' .  $eol;
			$data .= 'Content-Transfer-Encoding: 8bit' .  $eol . $eol;
			$data .= $value . $eol;
		}
	
	//file
	$data .= '--' . $mime_boundary . $eol;
	$data .= 'Content-Disposition: form-data; name="file"; filename="'.$filename.'"' . $eol; //Filename here
	$data .= 'Content-Type: application/octet-stream; charset=UTF-8' . $eol;
	$data .= 'Content-Transfer-Encoding: binary' . $eol . $eol;
	$data .= $file_body . $eol;
	$data .= "--" . $mime_boundary . "--" . $eol . $eol; // finish with two eol's
	
	//headers
	$header .= 'User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)' . $eol;
	$header .= 'Content-Type: multipart/form-data; boundary='.$mime_boundary . $eol;
	$header .= 'Host: hy.wikisource.org'. $eol;
	$header .= 'Cookie: '. $cookies . $eol;
	$header .= 'Content-Length: ' . strlen($data) . $eol;
	$header .= 'Connection: Keep-Alive';
	
	$params = array('http' => array(
					  'method' => 'POST',
					  'header' => $header,					  
					  'content' => $data					  
				   ));
	 
	$ctx = stream_context_create($params);
	//var_dump($params);
	$response = @file_get_contents($destination, FILE_TEXT, $ctx);

	return $response;
}

You'll need to get edit token, and also provide cookies. Hope it will save an hour or two for some people. --Xelgen (talk) 02:33, 6 March 2014 (UTC)Reply

Real world wiki functions in VBscript/Windows Shell[edit]

After many hours of working my way through this I thought it might be helpful to provide the functions I've created that allow uploading a file. Yes it's long and not pretty, but is functional and should help provide pointers in the right direction.

  • Variable types are commented out as this was developed in MsAccess and then ported to Windows shell script (I was apparently bad in a past life).
  • Code written to upload images but should work for anything - the file to be uploaded is usually referred to as strImageFileName
  • File paths assumed to have a trailing slash (eg "C:\data\upload\")
  • Functions wikiLogin() and getEditToken() included for completeness
Const MULTIPART_BOUNDARY = "---------------------------0123456789012"
'This string shouldn't occur in the file or data you are using

'Function uploadFileToWiki(strUser As String, strPassword As String, strPagename As String, strImageFileName As String, strError As String) As Boolean
Function uploadFileToWiki(strUser, strPassword, strPagename, strPath, strImageFileName, strError)

    Dim xmlhttp 'As MSXML2.ServerXMLHTTP
    Dim xDoc 'As MSXML2.DOMDocument

    Dim strEditToken 'As String
    Dim vPostData 'As Variant
    Dim bResult 'As Boolean
    Dim strDataPairs 'As String

    Set xmlhttp = CreateObject("MSXML2.ServerXMLHTTP")

    bResult = wikiLogin(xmlhttp, strUser, strPassword, strError)
    If (bResult = False) Then
        wscript.echo "Login failed: [" & strError & "]"
        Exit Function
    End If

    bResult = getEditToken(xmlhttp, strPagename, strEditToken, strError)

    strDataPairs = ""
    strDataPairs = strDataPairs & "token=" & strEditToken & "|"
    strDataPairs = strDataPairs & "ignorewarnings=1|"
    strDataPairs = strDataPairs & "format=xml|"
    strDataPairs = strDataPairs & "filename=" & strImageFileName
    vPostData = generateImageUploadPostData(strDataPairs, strPath, strImageFileName)


'---- submit update --------------------------------

    xmlhttp.Open "POST", WIKI_URL & "api.php?action=upload" & "&token=" & URLEncode(strEditToken)
    'WIKI_URL is your equivalent of "https://en.wikipedia.org/w/"
    'URLEncode() is a function to encode special characters - not hard to find one

    xmlhttp.setRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)"
    xmlhttp.setRequestHeader "Content-Type", "multipart/form-data; boundary=" & MULTIPART_BOUNDARY
    xmlhttp.setRequestHeader "Host", WIKI_HOST 'eg mywiki.hostname.com
    xmlhttp.setRequestHeader "Content-Length", CStr(Len(vPostData))
    xmlhttp.setRequestHeader "Connection", "Keep-Alive"
    xmlhttp.send vPostData

'---- retrieve and print result --------------------------------

    Set xDoc = CreateObject("MSXML2.DOMDocument")
    xDoc.LoadXML (xmlhttp.responseText)

    strError = Left(xmlhttp.responseText, 700)
    'wscript.echo strError

    If ("Success" = xDoc.SelectSingleNode("api").SelectSingleNode("upload").Attributes.getNamedItem("result").Text) Then
        uploadFileToWiki = True
    Else
        uploadFileToWiki = False
    End If

    Set xmlhttp = Nothing

End Function


Private Function wikiLogin(ByRef xmlhttp, strUser, strPass, strError)
'Private Function wikiLogin(ByRef xmlhttp As MSXML2.ServerXMLHTTP, strUser As String, strPass As String, strError As String) As Boolean

    Dim xDoc 'As MSXML2.DOMDocument

    wikiLogin = False
    Dim strResponse 'As String
    Dim strPostData 'As String
    Dim strLoginToken 'As String

    strPostData = "format=xml&lgname=" & URLEncode(strUser) & "&lgpassword=" & URLEncode(strPass) & "&lgdomain=" & URLEncode("LDAP")

'---- login start --------------------------------

    xmlhttp.Open "POST", WIKI_URL & "api.php?action=login", False
    xmlhttp.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
    xmlhttp.send strPostData

    Set xDoc = CreateObject("MSXML2.DOMDocument")
    xDoc.loadXML (xmlhttp.responseText)

    strLoginToken = "&lgtoken=" & URLEncode(xDoc.selectSingleNode("api").selectSingleNode("login").Attributes.getNamedItem("token").Text)
    strPostData = strPostData & strLoginToken

'---- (re-)login with wiki provided token --------------------------------
    xmlhttp.Open "POST", WIKI_URL & "api.php?action=login", False
    xmlhttp.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
    xmlhttp.send strPostData

    Set xDoc = CreateObject("MSXML2.DOMDocument")
    xDoc.loadXML (xmlhttp.responseText)

    strResponse = lcase(xDoc.selectSingleNode("api").selectSingleNode("login").Attributes.getNamedItem("result").Text)
'---- login complete --------------------------------

    'wscript.echo xmlhttp.responseText

    If (strResponse = "success") Then
        wikiLogin = True
    Else
        wikiLogin = False
        strError = strResponse
    End If

End Function

Private Function getEditToken(ByRef xmlhttp, strPageTitle, ByRef strEditToken, strError)
'Private Function getEditToken(ByRef xmlhttp As MSXML2.ServerXMLHTTP, strPageTitle As String, ByRef strEditToken As String, strError As String) As Boolean

    Dim xDoc 'As MSXML2.DOMDocument

'---- get edit token --------------------------------
    xmlhttp.Open "GET", WIKI_URL & "api.php?action=query&format=xml&prop=info&intoken=edit&titles=" & URLEncode(strPageTitle), False
    xmlhttp.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
    xmlhttp.send 'strPostData

    Set xDoc = CreateObject("MSXML2.DOMDocument")
    xDoc.loadXML (xmlhttp.responseText)

    On Error Resume Next
    strEditToken = ""
    strEditToken = xDoc.selectSingleNode("api").selectSingleNode("query").selectSingleNode("pages").selectSingleNode("page").Attributes.getNamedItem("edittoken").Text
    On Error GoTo 0

    'wscript.echo Left(xmlhttp.responseText, 700)

    If strEditToken = "" Then
        getEditToken = False
    Else
        getEditToken = True
    End If

End Function


'Private Function generateImageUploadPostData(strDataPairs As String, strPath As String, strFileName As String) As Variant
Private Function generateImageUploadPostData(strDataPairs, strPath, strFileName)

    'more or less from http://code.huypv.net/2012/06/vbs-upload-file-http-post.html

    Dim ado 'As ADODB.Stream
    Dim rs 'As ADODB.Recordset
    Dim lngCount
    Dim bytFormData 'As Variant
    Dim bytFormStart 'As Variant
    Dim bytFormEnd 'As Variant
    Dim bytFile 'As Variant
    Dim strFormStart 'As Variant
    Dim strFormEnd 'As Variant
    Dim strDataPair 'As Variant

    Const adLongVarBinary = 205
    'Read the file into a byte array
    Set ado = CreateObject("ADODB.Stream")
    ado.Type = 1
    ado.Open
    ado.LoadFromFile strPath & strFileName
    bytFile = ado.Read
    ado.Close

    'Create the multipart form data.
    'Define the end of form
    strFormEnd = vbCrLf & "--" & MULTIPART_BOUNDARY & "--" & vbCrLf
    'First add any ordinary form data pairs

    strFormStart = ""

    For Each strDataPair In Split(strDataPairs, "|")
        strFormStart = strFormStart & "--" & MULTIPART_BOUNDARY & vbCrLf
        strFormStart = strFormStart & "Content-Disposition: form-data; "
        strFormStart = strFormStart & "name=""" & Split(strDataPair, "=")(0) & """" & vbCrLf
        strFormStart = strFormStart & "Content-Type: text/plain; charset=UTF-8" & vbCrLf
        strFormStart = strFormStart & "Content-Transfer-Encoding: 8bit"
        strFormStart = strFormStart & vbCrLf & vbCrLf
        strFormStart = strFormStart & Split(strDataPair, "=")(1)
        strFormStart = strFormStart & vbCrLf
    Next

    'Now add the header for the uploaded file
    strFormStart = strFormStart & "--" & MULTIPART_BOUNDARY & vbCrLf
    strFormStart = strFormStart & "Content-Disposition: form-data; "
    strFormStart = strFormStart & "name=""" & "file" & """; "
    strFormStart = strFormStart & "filename=""" & strFileName & """"
    strFormStart = strFormStart & vbCrLf
    strFormStart = strFormStart & "Content-Type: application/octet-stream" '; charset=UTF-8"
    strFormStart = strFormStart & vbCrLf
    strFormStart = strFormStart & "Content-Transfer-Encoding: binary"
    strFormStart = strFormStart & vbCrLf & vbCrLf

    'Create a recordset large enough to hold everything
    Set rs = CreateObject("ADODB.Recordset")
    rs.Fields.Append "FormData", adLongVarBinary, Len(strFormStart) + LenB(bytFile) + Len(strFormEnd)
    rs.Open
    rs.AddNew
    'Convert form data so far to zero-terminated byte array
    For lngCount = 1 To Len(strFormStart)
        bytFormStart = bytFormStart & ChrB(Asc(Mid(strFormStart, lngCount, 1)))
    Next
    rs("FormData").AppendChunk bytFormStart & ChrB(0)
    bytFormStart = rs("formData").GetChunk(Len(strFormStart))
    rs("FormData") = ""
    'Get the end boundary as a zero-terminated byte array
    For lngCount = 1 To Len(strFormEnd)
        bytFormEnd = bytFormEnd & ChrB(Asc(Mid(strFormEnd, lngCount, 1)))
    Next
    rs("FormData").AppendChunk bytFormEnd & ChrB(0)
    bytFormEnd = rs("formData").GetChunk(Len(strFormEnd))
    rs("FormData") = ""
    'Now merge it all
    rs("FormData").AppendChunk bytFormStart
    rs("FormData").AppendChunk bytFile
    rs("FormData").AppendChunk bytFormEnd
    bytFormData = rs("FormData")
    rs.Close

    generateImageUploadPostData = bytFormData 'strFormStart

End Function

Hope it helps -- Qwaddles (talk) 23 April 2014

mw.Api[edit]

Is it at all possible to use mw.Api with this part of the API? It seems to only accepts an object, whereas this needs a FormData object. I'd rather not loose the benefits of mw.Api and use bare $.ajax. 124.180.3.50 07:51, 24 August 2014 (UTC)Reply

Uploading Local Files with non-English characters in name[edit]

Uploading Local Files with non-English characters in name, with python 3.4.3 + requests 2.7 plugin.

MW version 1.23.1.

I get this error:

 {'error': {'code': 'badupload_file', 'info': 'File upload param file is not a file upload; be sure to use multipart/form-data for your POST and include a filename in the Content-Disposition header.'}}

— Preceding unsigned comment added by Boxsnake (talkcontribs)

We are now on MediaWiki version 1.35.0-wmf1 but here's the answer for python3: the requests module relies on urllib3 in order to handle the filename, and things go awry there. You can work around the issue by rfc2047-encoding the title and using that converted title as the value of the title (first field) in the tuple set as the value of 'file'. That is, you would do {'file': (converted_title, open(path, 'rb'), 'multipart/form-data')}. See the requests bug on github for more info and for sample code. -- ArielGlenn (talk) 19:48, 16 October 2019 (UTC)Reply

Verify SSL[edit]

Is there a possibility to disable checking ssl certificates?

Mostly CURLOPT_SSL_VERIFYPEER => false would solve this problem.

$user = $this->getUser(); doesn't get a user[edit]

Here's the first bit of my apiupload script. The only changed bit is the wfdebug line.
42: $user = $this->getUser();
43: wfDebug( "ApiUpload: ".$user->getId()." , I guess.");

It returns:
ApiUpload: 0 , I guess.
Any idea why it seems like there should be a use stuck in that object, because it's whats causing my image uploads to fail, but I don't know why there isn't one. BTW, yes, I'm logged in.

Minimal working JavaScript[edit]

Here is a really simple no-frills working example in JavaScript, without event handling etc. It assumes the following:

1) an HTML input element that is of type "file" and has ID = "localfile", name = "localfile"
2) a valid csrf token in variable "yourCsrfToken" (this is not something specific to file upload. Look elsewhere if you don't know about csrf tokens in Mediawiki)
3) the URL of your wiki's API in variable "yourMediaWikiApiUrl"
4) a file named "somefile.jpg" has not already been uploaded to the wiki.

var yourCsrfToken = <VALID_CSRF_TOKEN>;
var yourMediaWikiApiUrl = <YOUR_API_URL>;
var localfile = document.getElementById("localfile");
var file = localfile.files[0];
var fileName = "blueflower.jpg";
var comment = `
=={{int:filedesc}}==
{{Information
|description={{en|1=A blue flower}}
|date={{subst:{{CURRENTYEAR}}-{{CURRENTMONTH}}-{{CURRENTDAY2}}}}
|source={{own}}
|author=~~~
|permission=
|other versions=
}}
=={{int:license-header}}==
{{self|cc-by-sa-4.0}}
`
var request = new XMLHttpRequest();
request.open('POST', yourMediaWikiApiUrl, false);
var formData = new FormData();
formData.append("action", "upload");
formData.append("filename", fileName);
formData.append("comment", comment);
formData.append("token", yourCsrfToken);
formData.append("file", file);
request.setRequestHeader("Content-Disposition", "form-data");
request.send(formData);
console.log(request.response);

Assuming the user has selected a file through the input element named "localfile", this will upload that file to the wiki, giving it the name "somefile.jpg". You can check the response in your console. --Henryfunk (talk) 21:06, 13 May 2018 (UTC)Reply

Thanks Henryfunk. I encourage you to also add the page desciption.
  • comment: Upload comment. Also used as the initial page text for new files if text is not specified.
Yug (talk) 17:06, 21 September 2020 (UTC)Reply
I added it. Yug (talk) 17:16, 21 September 2020 (UTC)Reply

uploading images stored as base64 data[edit]

I am trying to use the api to upload an image that has been extracted from an html document which is in base64 data format.

Could you tell me:

  • is api upload able to upload images in this format?
  • what parameters do I need to give the api call (preferably in javascript using ajax to make the api call)

Many thanks DuncanCrane (talk) 14:49, 12 June 2020 (UTC)Reply

Structured data?[edit]

What should be the way to add structured data (eg when uploading images to Wikimedia Commons)? I'm not very familiar with it but it seems Wikimedia is moving that way and some of the data that's uploaded in the image page description (eg geocoordinates) could also be added as structured data at upload time given a field in this API call.

Structured data is not part of the page description nor the documented API call so I guess it can't currently be added as part of the upload call.

Usually a bot will pick it up but that doesn't seem to be the right way, nor is making a separate API call.

--Trougnouf (talk) 14:05, 18 March 2021 (UTC)Reply

Is a BOT really necessary?[edit]

Hello to all. I am building a tool on Toolforge where users are supposed to be allowed to send their images of objects of a Museum collection. I was trying to implement this functionallity and wasn't successful. Reading the examples, it seems that I have to request a Bot? Until today, I only created tools using OAuth consumers; The users logged in, allowed the tool, and then every contribution used the API on Wikidata. Below is what I tried to implement. I'm using Python and Flask. Ederporto (talk) 00:21, 23 May 2021 (UTC)Reply

This page is not really watched (I followed this from phabricator). If you ask at Project:Support_desk, there's a better chance of you getting a response. Ammarpad (talk) 20:56, 25 May 2021 (UTC)Reply
Ammarpad I made a post there, as you suggested. Thank you! Good contributions, Ederporto (talk) 21:51, 25 May 2021 (UTC)Reply
code 
client_key = app.config['CONSUMER_KEY']
client_secret = app.config['CONSUMER_SECRET']

session = OAuth1Session(client_key,
                        client_secret=client_secret,
                        resource_owner_key=session['owner_key'],
                        resource_owner_secret=session['owner_secret'])
                        
url = "https://test.wikipedia.org/w/api.php"

crsf_token = get_token()

params = {
    "action": "upload",
    "filename": <filename>,
    "format": "json",
    "token": csrf_token,
    "ignorewarnings": 1
}

file = {'file': (<filename>, open(<filepath>, 'rb'), 'multipart/form-data')}

response = session.post(url, files=file, data=params)
data = response.json()

return data


result 
{
"error":
  {
    "code":"permissiondenied",
    "docref":"See https://commons.wikimedia.org/w/api.php for API usage. Subscribe to the mediawiki-api-announce mailing list at &lt;https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce&gt; for notice of API deprecations and breaking changes.",
    "info":"The action you have requested is limited to users in one of the groups: *, [[Commons:Users|Users]]."
  },
  "servedby":"mw1278"
}


Doc: Upload warnings - duplicate[edit]

At "Upload warnings" it says:

"duplicate: The uploaded file exists under a different (or the same) name. ..."

The "(or the same)" part seems potentially incorrect. (depending on the used mw-verion I guess)

As:

While test uploading a duplicate file to its current location/img-page-name.

I did get the "exists"(+name) & "nochange"(+timestamp) warnings. (Doc say "no-change" btw)

But there was no "duplicate" warning. (which seems a bit overkill away considering exists+nochange comes down to the same thing.)

(MediaWiki: 1.36.1)

... Hmm: (message editing) Switching from Visual to Source like to eats <br> statements.

... Erm: And then suddenly I lost all linebreaks in my message. ??? ... Ok!. Only double hard-line breaks it is.

MvGulik (talk) 16:03, 8 October 2022 (UTC)Reply

Upload duplicate[edit]

Hello,

I am trying hard to get this API work, but I have a really annoying problem.

I have some custom extension which requires new revision for files on some calls (rare, actually, but very important).

To avoid working with the DB directly, I decided to run via API call with this Upload API. My operation requires just create new revision for the existing file, so I send URL with one of the existing files from my wiki and try to re-upload it to beautifully create new revision. I use ignorewarnings=1. But all the time I get an error:

{"error":{"code":"fileexists-no-change","info":"The upload is an exact duplicate of the current version of...

Is there any chance to bypass this error, without hacking my wiki or writing custom complete upload API?


This is a very important! Please, help! Arsenii Gorkin (talk) 22:33, 1 November 2023 (UTC)Reply