2012-09-02 41 views
2

我想通過使用代碼here的Python CGI腳本使用單個表單域上傳多個文件。較新的瀏覽器似乎支持此功能,每herehere。 HTML表單看起來非常簡單:通過Python通過單個表單域上傳多個文件CGI

<input name="file" type="file" multiple="" />

使用此表來選擇兩個文件名file0file1將導致以下每HTML5 input multiple attribute

file=file0&file=file1

我最初認爲這將是一個排序數組,但它似乎使用&符號分隔。

我嘗試修改代碼並使用以下代碼添加for語句以遍歷表單字段中指定的每個文件,但未成功(請參閱下面的錯誤)。如果使用for語句不是最佳路線,那麼我也可以使用其他可能使用Python的想法。

#!/usr/bin/python 
import cgi, os 

form = cgi.FieldStorage() 

# Generator to buffer file chunks 
def fbuffer(f, chunk_size=10000): 
    while True: 
     chunk = f.read(chunk_size) 
     if not chunk: break 
     yield chunk 

for fileitem in form['file']: 

    # A nested FieldStorage instance holds the file 
    fileitem = form['file'] 

    # Test if the file was uploaded 
    if fileitem.filename: 

     # strip leading path from file name to avoid directory traversal attacks 
     fn = os.path.basename(fileitem.filename) 
     f = open('/var/www/domain.com/files' + fn, 'wb', 10000) 

     # Read the file in chunks 
     for chunk in fbuffer(fileitem.file): 
     f.write(chunk) 
     f.close() 
     message = 'The file "' + fn + '" was uploaded successfully' 

    else: 
     message = 'No file was uploaded' 

    print """\ 
    Content-Type: text/html\n 
    <html><body> 
    <p>%s</p> 
    </body></html> 
    """ % (message,) 

單個文件選擇的誤差:

Traceback (most recent call last):, referer: https://www.domain.com/files/upload.htm 
    File "/usr/lib/cgi-bin/test.py", line 13, in <module>, referer: https://www.domain.com/files/upload.htm 
    for fileitem in form['file']:, referer: https://www.domain.com/files/upload.htm 
    File "/usr/lib/python2.6/cgi.py", line 518, in __iter__, referer: https://www.domain.com/files/upload.htm 
    return iter(self.keys()), referer: https://www.domain.com/files/upload.htm 
    File "/usr/lib/python2.6/cgi.py", line 583, in keys, referer: https://www.domain.com/files/upload.htm 
    raise TypeError, "not indexable", referer: https://www.domain.com/files/upload.htm 
TypeError: not indexable, referer: https://www.domain.com/files/upload.htm 
Premature end of script headers: test.py, referer: https://www.domain.com/files/upload.htm 

兩個文件選擇的誤差:

Traceback (most recent call last):, referer: https://www.domain.com/files/upload.htm 
    File "/usr/lib/cgi-bin/test.py", line 19, in <module>, referer: https://www.domain.com/files/upload.htm 
    if fileitem.filename:, referer: https://www.domain.com/files/upload.htm 
AttributeError: 'list' object has no attribute 'filename', referer: https://www.domain.com/files/upload.htm 
Premature end of script headers: test.py, referer: https://www.domain.com/files/upload.htm 

如果.filename引用都被刪除時,產生第三誤差,相同的單個或兩個文件被選中:

Traceback (most recent call last):, referer: https://www.domain.com/files/upload.htm 
    File "/usr/lib/cgi-bin/test.py", line 24, in <module>, referer: https://www.domain.com/files/upload.htm 
    fn = os.path.basename(fileitem), referer: https://www.domain.com/files/upload.htm 
    File "/usr/lib/python2.6/posixpath.py", line 111, in basename, referer: https://www.domain.com/files/upload.htm 
    i = p.rfind('/') + 1, referer: https://www.domain.com/files/upload.htm 
AttributeError: 'list' object has no attribute 'rfind', referer: https://www.domain.com/files/upload.htm 
Premature end of script headers: test.py, referer: https://www.domain.com/files/upload.htm 

回答

2

刪除for file in form。該錯誤意味着form['file']是一個列表。

添加到html表格:method=post enctype=multipart/form-data

import shutil 

if 'file' in form: 
    filefield = form['file'] 
    if not isinstance(filefield, list): 
     filefield = [filefield] 

    for fileitem in filefield: 
     if fileitem.filename: 
      fn = secure_filename(fileitem.filename) 
      # save file 
      with open('/var/www/domain.com/files/' + fn, 'wb') as f: 
       shutil.copyfileobj(fileitem.file, f) 
+0

更新了'for'語句和新的相應錯誤。建議我也更改保存方法?如果是這樣,我應該刪除for語句下的所有現有代碼嗎?謝謝 – Astron

+0

@Astron:我已經更新了答案。 – jfs

0

我不知道cgi庫是否支持上傳多個文件,但是你的錯誤很簡單:你已經在HTML中調用了你的字段file[],但是在Python中你只需要指向file。他們不一樣。我建議簡單地刪除PHP主題並調用該字段只需file

+0

感謝您的反饋。 PHP-ism被刪除並更新了有問題的錯誤。 – Astron

相關問題