File Uploading and Handling
kernel 這個字在 Image Processing 領域代表一種濾鏡,基本是一個小矩陣,正中間代表「新影像中的某一個像素」,其周邊的值代表權重。
除了用 Image 外,也可以使用 File 來上傳圖檔,主要差別在於 File 不會主動產生縮圖。利用 collective.pdfpeek 可以為上傳的 PDF 建立縮圖。
轉 PDF 用 jsPdf 應該夠,若要全圖pdf可用html2canvas轉圖再轉pdf, 若要有由docx或xlsx或odt等轉pdf,由後端做比較容易。用html2canvas轉出canvas再轉點陣圖即可,記得html2canvas要設定scale放大(2~3倍),也就是類似anti-aliasing,否則解析度等同於截圖,轉出pdf會很糊。 https://www.youtube.com/watch?v=vfuAVi48S6w 這個似乎不用 canvas 通常基本html沒問題,若上面dom比較複雜或有繪圖套件所生成的svg,通常會爆版,都轉成圖再轉出pdf會比較簡單。
上傳 _ 開頭的檔名會產生錯誤 Fetch File (Image, PDF) from URL: izug.seantis.dir.events/import.py
Image Attribute for EEA FacetedNavigation Thumbnail: Behavior + IObjectModifiedEvent possible example: eea.alchemy
collective.upload
read metadata form IPTC IIM properties if present collective.documentfile jQuery File Upload library
wildcard.foldercontents (Plone 4.3.4 pins) 支援批次上傳檔案的功能,在 Plone 5 則內建納入這個模組,名稱定為 plone.foldercontents,既有的類似模組也很多。
Archetypes 的 ATImage 和 ATFile 都繼承自 ATBlob,透過 ImageMixin 達到向後相容的效果。OFS 圖檔昇級轉換到 Dexterity 的討論,用 NamedBlobFiles 取代 OFSImage 的範例: collective.pdfpeek。
不同於一般方式,要在 form 裡建立一個 FileUpload 的物件欄位,想要取得物件路徑,可以使用 REQUEST.yourfile.filename 也就是 filename 屬性值來取得物件路徑。
NamedFile 不會把檔案存到 var/blobstorage 裡,NamedBlobFile 才會,除此之外,兩者功能相同。
參考 plone.app.contenttypes/tests/test_image.py 和 content.py 範例:
from plone.namedfile.file import NamedBlobImage filename = u'myfile.png' obj = createContentInContainer(folder, 'Image', image=NamedBlobImage(data=open(filename, 'r').read(), filename=filename))
<div tal:define="picture nocall:context/picture" tal:condition="nocall:picture"> <img tal:attribute="src string:${context/absolute_url}/@@download/picture/${picture/filename}; height picture/_height | nothing; width picture/_width | nothing;" /> </div>
另一個範例
<div tal:define="images view/images" tal:condition="images"> <span tal:repeat="obj images"> <img src="" alt="" tal:attributes="src string:${obj/getURL}/image/preview" /> </span> </div>
/portal_skins/archetypes/at_download: AttributeError: 'RequestContainer' object has no attribute 'getWrappedField' BlobWrapper vs File Instance: uwosh.pfg.d2c at_download stored as blobs make view override optional
plone.app.imagecropping: Generate cropped scales instead of uncropped scales after storage._cleanup() has run 版本議題造成 ImportError 錯誤 JPEG CMYK 模式在新版能處理得更好
view = self.img.restrictedTraverse('@@crop-image') traverse = self.portal.REQUEST.traverseName scales = traverse(self.img, '@@images') uncropped_thumb = scales.scale('image', 'thumb')
上傳限制
Web Server 預設會有上傳的大小限制,以 Nginx 為例,在 /etc/nginx/proxy.conf 可找到 client_max_body_size 10m; 設定值。
Plone5 + HTTPs 造成檔案上傳 500Kb 限制 Dexterity Validator for Uploaded Files
# -*- coding: utf-8 -*- from plone.namedfile.interfaces import INamedBlobImageField # from plone.app.contenttypes.interfaces import IImage from zope.interface import Invalid from z3c.form import validator # 1 MB size limit MAXSIZE = 1024 * 1024 class ImageFileSizeValidator(validator.FileUploadValidator): def validate(self, value): super(ImageFileSizeValidator, self).validate(value) if value.getSize() > MAXSIZE: raise Invalid("Image is too large (to many bytes)") validator.WidgetValidatorDiscriminators(ImageFileSizeValidator, # context=IImage, field=INamedBlobImageField)
<adapter factory=".validators.ImageFileSizeValidator" />
限制上傳的檔案類型 限制圖檔類型 上傳圖檔時限制 PDF 格式: Archetypes IObjectPostValidation Event Subscriber to Limit File Types
限制上傳圖檔的尺寸 IWebDAVObjectInitializedEvent FileSize Validator for Dexterity
File Image In Batch Via Zip: atreal.massloader
Image Contents Validation Methods among Archetypes Versions
Image Getter: collective.loremipsum
Using is_zipfile on ZPublisher.HTTPRequest.FileUpload
限制成員上傳的容量 限制上傳容量 Products.feedfeeder 範例 判斷上傳檔案是否存在
<span tal:condition="context/attachment/get_size">ATTACHMENT</span>
collective.quickupload wildcard.media list index out of range wildcard.media 相容性
Download
Archetype File with restrictedtraverse
eea.pdf: 透過 PDF 下載內容 eea.converter 利用 urllib.urlretrieve('http://site.net/shared/'+filename, filename) 可以批次下載圖檔
Products.ATContentTypes/lib/imagetransform.py getImageAsFile()
image = self.getImageAsFile() image2 = StringIO() if image is not None: img = PIL.Image.open(image) del image fmt = img.format img = img.transpose(method) img.save(image2, fmt, quality=zconf.pil_config.quality)
obj = app.restrictedTraverse(„path/to/object) data = str(obj,file.data)
線上顯示
Google Docs Microsoft Office Auto Rotate Dexterity Images Based on EXIF Information
<object tal:condition="python:content_type.endswith('pdf')" class="viewembededfile" type="application/pdf" data="" tal:attributes="data location"> <a href="" tal:attributes="href location"> Click to Download </a> <embed src="" class="viewembededfile" type="application/pdf" tal:attributes="src location"> </embed> </object>
collective.documentviewer: PDF 和 Office 檔案都能線上顯示,進行文字辨識。LibreOffice 4.1 與 docsplit 版本問題,Archetypes 與 Dexterity 參照問題。
wc.pageturner: 搭配 Flex Paper 和 SWFtool 進行線上顯示。
collective.pdfjs: 搭配 Mozilla JavaScript PDF Reader 或 Native Reader Plugin 進行線上顯示。
Embedded PDF in File View: 搭配 HTTP Content Type 和 Native Reader Plugin 進行線上顯示。
z3c.rml: ReportLab's RML PDF generation XML format
IE 瀏覽器顯示 Flash z3c.form with NamedImageFieldWidget
在 Portlet 顯示圖檔 在 Related Item 顯示圖檔
resolveuid images jQuery LightBox PrettyPhoto
MediaElement.js: collective.mediaelementjs
CSS Paged Media PDF 中文字型可能要搭配新版 freetype 才行
辨識 OCR H264: wildcard.media OSX Safari avconv params
import requests url = "https://" payload = "token=" headers = {'Content-Type': 'application/x-www-form-urlencoded'} response = requests.post(url, headers=headers, data=payload)
tarfile.open(io.BytesIO(response.content), 'r:bz2') https://docs.python.org/3/library/tarfile.html x-www-form-urlencoded 不用指定 header,直接 requests.post(url, data={'token': 'TOKEN'}) 就可以了 上傳 Zip 檔案可以建立內容 collective.documentfusion: fusion of the variables and bookmarks of a file field, LibreOffice as a service
TinyMCE Batch Uploading PDF Image Caption: html-to-captioned
PNG 支援背景透明功能: z3c.rml transparent
存取檔案系統
>>> fldr['2011']['09']['China-and-the-West.pdf'].file <plone.namedfile.file.NamedBlobFile object at 0x7f81a3c45398> >>> dir(fldr['2011']['09']['China-and-the-West.pdf'].file) ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__getstate__', '__hash__', '__implemented__', '__init__', '__module__', '__new__', '__providedBy__', '__provides__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_data', '_getData', '_p_activate', '_p_changed', '_p_deactivate', '_p_delattr', '_p_estimated_size', '_p_getattr', '_p_invalidate', '_p_jar', '_p_mtime', '_p_oid', '_p_serial', '_p_setattr', '_p_state', '_setData', 'data', 'filename', 'getSize', 'open', 'openDetached', 'size'] >>> fldr['2011']['09']['China-and-the-West.pdf'].file.filename u'China-and-the-West.pdf' >>> fldr['2011']['09']['China-and-the-West.pdf'].file.__dict__ {'_blob': <zodb.blob.blob object at 0x7f81a3c45488>, 'contentType': 'application/pdf', 'filename': u'China-and-the-West.pdf', 'size': 223747}
Bad Images: plone.app.imagecropping
>>> from zope.annotation import IAnnotations >>> from plone.app.imagecropping import PAI_STORAGE_KEY >>> all_images = app.Plone.portal_catalog(portal_type='Image') >>> bad_images = [x.getObject() for x in all_images if PAI_STORAGE_KEY in IAnnotations(x.getObject())] >>> dont_care = [(IAnnotations(x).pop(PAI_STORAGE_KEY), x.setModificationDate()) for x in bad_images] >>> import transaction >>> transaction.commit()
批次下載圖檔
imgs = {'folder1': ['img1.jpg', 'img2.png'], 'folder2': ['myimg.png']} for i in imgs.keys(): os.chdir('/tmp/download') os.mkdir(i) os.chdir('/tmp/download/'+i) for j in imgs[i]: urllib.urlretrieve('http://site.com/folder/'+i+'/'+j, j)
IIIF
http://iiif.io/api/presentation/2.0/ http://dms-data.stanford.edu/data/manifests/Walters/qm670kv1873/manifest.json http://iiif.io/api/presentation/2/context.json http://github.com/IIIF/showcase.iiif.io http://github.com/IIIF/mirador http://gist.github.com/sdellis/5d3b0da75c4b301ecbeb http://iiif.io/api/image/2.0/ http://iiif.io/api/presentation/2.0/example/fixtures/collection.json http://iiif.io/api/presentation/2.0/example/fixtures/1/manifest.json