我在 Django 中遇到了 PIL(Python 图像库)的一个主要问题,并且已经跳过了很多圈,到目前为止还无法弄清楚问题的根源是什么。
问题基本上分解为无法通过 Django 管理员中的 ImageField 上传 JPEG 图像。但问题并不像安装 libjpeg 那样简单。
首先,我安装了 PIL(通过 Buildout),并在安装后意识到我没有安装 libjpeg,因为 JPEG 支持不可用。
我自己没有设置服务器,我只是假设它没有安装,我从源代码编译了 libjpeg 8。这最终出现在我的/usr/local/lib/目录中。我清除了我的 Buildout 文件并重建了所有内容。这次当 PIL 编译时,我有 JPEG 支持。但是我去了 Django Admin 并尝试通过 ImageField 上传 JPEG,但没有成功。我收到“上传有效图片。您上传的文件不是图片或损坏的图片”错误。作为一个测试,我打开了一个 Djano shell 并运行了以下命令:
> import Image
> i = Image.open( "/absolute_path/file.jpg" )
> print i
<JpegImagePlugin.JpegImageFile image mode=RGB size=940x375 at 0x7F908C529BD8>
这运行没有错误,并表明 PIL 能够打开 JPEG。
做了一些阅读后,我遇到了这个线程: Is it possible to control which libraries apache uses?
看起来 PHP 也使用 libjpeg 并且在 Django 之前加载,因此之前加载了 libjpeg 6.2。这是使用lsof时显示的:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
apache2 2561 www-data mem REG 202,1 146032 639276 /usr/lib/libjpeg.so.62.0.0
所以我的想法是我应该使用 libjpeg 6.2。所以我删除了位于我的/usr/local/lib目录中的 libjpeg。重新阅读 PIL 安装说明后,我意识到我可能没有 PIL 需要的 libjpeg 的 dev/header 文件。所以我还使用 aptitude 卸载程序(sudo aptitude remove libjpeg62)卸载了 libjpeg。然后为了确保我得到了 PIL 需要的头文件,我使用 aptitude 安装了 libjpeg:(sudo aptget install libjpeg62-dev)。
从这里我清理了我的 Buildout 目录,然后重新运行 Buildout,它又重新安装了 PIL。再次,我有 JPEG 支持,现在使用 libjpeg62。
所以我去 Django Admin 中测试。仍然不支持JPEG。所以我想测试一下对 JPEG 的支持,看看异常是否没有被处理,会抛出什么样的错误。所以在我的主页视图中,我添加了以下代码来打开 JPEG 图像:
import Image
i = Image.open( "/absolute_path/file.jpg" )
v = i.verify()
然后我将 i 传递给 HTML 视图,以便轻松查看输出。我将这些更改部署到服务器并重新启动。我很惊讶没有看到错误并得到以下输出:
{{ i }} - <JpegImagePlugin.JpegImageFile image mode=RGB size=940x375 at 0x7F908C529BD8>
{{ v }} - None
所以在这一点上我真的很困惑:
- 为什么我可以成功打开 JPEG 而管理员却不能?
- 我错过了什么吗,这不是 libjpeg 的问题吗?
- 如果 libjpeg 没有问题,为什么我可以毫无问题地上传 PNG?
任何帮助将不胜感激,我已经为此调试了 2 天,但没有运气。
设置: 1. Rackspace 云服务器 2. Ubuntu 10.04 3. Django 1.2.3(通过 Buildout 安装) 4. PIL 1.1.7(通过 Buildout 安装) 5. libjpeg 6.2(通过 aptitude 安装(sudo aptget install libjpeg62-dev)