2

I am trying to upload an XML with unicode content to a FTP server using ftplib, but getting the following exception when I try to upload the using storbinary method. The XML data is properly encoded to unicode (utf-8), I have made sure of that, I am not sure as to why storbinary is trying to encode it to 'ascii' while uploading. Can anyone please help?


--> 429         ftp.storbinary("STOR file.xml", xml)
    430 
    431     def run(self):

/usr/lib/python2.7/ftplib.pyc in storbinary(self, cmd, fp, blocksize, callback, rest)
    463             buf = fp.read(blocksize)
    464             if not buf: break
--> 465             conn.sendall(buf)
    466             if callback: callback(buf)
    467         conn.close()

/usr/lib/python2.7/socket.pyc in meth(name, self, *args)
    222 
    223 def meth(name,self,*args):
--> 224     return getattr(self._sock,name)(*args)
    225 
    226 for _m in _socketmethods:

UnicodeEncodeError: 'ascii' codec can't encode character u'\xae' in position 3368: ordinal not in range(128)

asp
  • 621
  • 8
  • 18
  • It looks like it's a `unicode` object, so it's not encoded at all. – Cairnarvon Feb 24 '13 at 09:56
  • Is `xml` a file object? If not, use `StringIO` to create a file-like object from your xml string. – Austin Phillips Feb 24 '13 at 10:42
  • @AustinPhillips:Yes, I build the XML and use the StringIO object to pass it on to ftplib. – asp Feb 24 '13 at 13:15
  • @Cairnarvon: I did not understand what you meant, the string I write to the StringIO instance is an unicode instance, and just make sure about the encoding, I even tried adding a ".encode("utf-8")" to the string before writing to the StringIO object. – asp Feb 24 '13 at 13:17
  • @asp Please provide a minimal example showing the generation of the unicode string. – Austin Phillips Feb 24 '13 at 22:00
  • @AustinPhillips, please find the code below; Comments seems to be removing my formatting, pastebin link below; http://pastebin.com/GugTLRQJ – asp Mar 03 '13 at 14:21

2 Answers2

1

You should pass a file opened in a binary mode to ftp.storbinary(). For example, if you want to upload a Unicode string as a filename file:

import io

assert isinstance(unicode_string, unicode)
file = io.BytesIO(unicode_string.encode("utf-8"))
ftp.storbinary("STOR filename", file)

If unicode_string contains xml; make sure that the character encoding used in the xml declaration is consistent with the encoding you use to store the file.

jfs
  • 399,953
  • 195
  • 994
  • 1,670
  • I use a StrinIO instance to pass to the storbinary method. – asp Feb 24 '13 at 13:19
  • @asp: `StringIO` works with both Unicode strings and bytestrings in Python 2. Use `BytesIO` to make it explicit that only bytes are allowed. – jfs Feb 24 '13 at 14:09
0

I was able to find the solution, the comment by @Cairnarvon was partially correct, I was encoding the string, but there were other bits of the string written to the StringIO instance that were not encoded. Finally I ended up creating the XML bit and encoding it as a whole. You can see my code in the pastebin link below;

http://pastebin.com/GugTLRQJ

asp
  • 621
  • 8
  • 18