API talk:Upload

From MediaWiki.org
Jump to navigation Jump to search

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)

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

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)

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)

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)

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

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)

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)

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

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)

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)

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)

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)

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)

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)


...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)

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)

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)

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)

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)

           $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)

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)

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)

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)

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)

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)

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)

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)

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 example with upload of image[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 = "somefile.jpg";
var request = new XMLHttpRequest();
request.open('POST', yourMediaWikiApiUrl, false);
var formData = new FormData();
formData.append("action", "upload");
formData.append("filename", fileName);
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)

No Bot related parameter.[edit]

Crap ... While some other generally used API modules/functions/actions/whatever have options that do 'not' hide a bot-account related action from the default 'Recent changes' page (Hide bots == True), API:upload seems to have none of that. While I'm sure that in some cases users would like a particular upload to 'not' be a hidden action (well ... I at least know one user that would have liked a choice in the matter). --MvGulik (talk) 03:05, 14 June 2018 (UTC)