Cách gửi và nhận file qua sftp bằng thư viện pyftp của Python

Trong nhiều trường hợp ta cần gửi hoặc nhận file qua sftp cho bảo mật. Ngôn ngữ Python có cho phép ta làm việc này với thư viện pysftp.

Đầu tiên cần cài đặt thư viện pysftp bằng pip:

pip install pysftp

Mình đã thử bằng nhiều cách trên mạng nhưng mãi mới có được cách sau, ví dụ và giải thích code luôn:

import pysftp

cnopts = pysftp.CnOpts()
cnopts.hostkeys = None
try:
	# Tạo kết nối qua sFTP
	with pysftp.Connection('192.168.xxx.xxx',username='admin',password='admin',cnopts = cnopts) as sftp:
		#Lấy 1 file từ server
		#file=sftp.get('đường dẫn full file trên server','thư mục ở local')
		#Mặc định không để 'thư mục ở local' thì sẽ để file mặc định tại thư mục code python
		file=sftp.get('/u02/extract/file_name.csv')
		#Chuyển 1 file từ local lên server
		#file=sftp.put('đường dẫn full file tại local','đường dẫn full file trên server')
		file=sftp.put('Extract_contacts_full20190301_tuy.csv','/u02/oracle/utl/extract/Extract_contacts_full20190301_tuy123.tcsv')
	sftp.close()
	print('Succeed')
except Exception as e:
	print('Error connect sfth Irdeto')

Như vậy là thành công, các bạn có thể tích hợp nó trong follow job của bạn như sau khi tạo file hoặc khi chuyển file xong thì gửi email…

Vấn đề Unicode với Python 3- Oracle

Đối với Python 3 thì string tự động được sử dụng với Unicode nhưng khi sử dụng Tiếng Việt thao tác xuống Database Oracle hoặc hiển thị dữ liệu Tiếng Việt lên thì bị lỗi.

Để khắc phục điều này khi sử dụng connect tới DB thì cần khai báo encoding và nencoding: cx_Oracle.connect(‘admin’,’admin’,dsn_tns,encoding=”UTF-8″, nencoding=”UTF-8″)

Ví dụ hoàn thiện với việc thêm mới dữ liệu Tiếng Việt:

#!/usr/bin/python

# -*- coding: utf8 -*-
from unicodedata import normalize
import cx_Oracle
cursor, connection = None, None
try:
    dsn_tns = cx_Oracle.makedsn('192.168.177.xxx' , 1522, 'orcl')
    connection = cx_Oracle.connect('admin','admin',dsn_tns,encoding="UTF-8", nencoding="UTF-8")
    cursor = connection.cursor()
    a=u"Lý do"
    b="reasons"
    c="INSERT INTO VN_TEMP_DIC (VN, EN,DAY_TIME,STATUS) VALUES ('%s','%s',sysdate,0)" % (a,b)
    cursor.execute(c)
    cursor.execute("COMMIT")
except cx_Oracle.DatabaseError as e:
    raise e
except Exception as e:
    raise e     
finally:
    if cursor != None:
        cursor.close()
    if connection != None:
        connection.close()


    

Ví dụ hoàn thiện với việc hiển thị dữ liệu tiếng Việt load từ DB:

#!/usr/bin/python
# -*- coding: utf8 -*-

import cx_Oracle
dsn_tns = cx_Oracle.makedsn('xxxxxxxxx' , 1522, 'orcl')
connection = cx_Oracle.Connection('admin','admin',dsn_tns,encoding="UTF-8", nencoding="UTF-8")
cur=connection.cursor()
content = 'however it not depend on column INDPOSTPONEADVANTAGES'
listword=content.split()
listr="";
for re in listword:
    listr=listr+"','"+re
listr=listr
listr=listr[3:]   
print(listr)
query="select a.EN,a.VN from VN_TEMP_DIC a where trim(a.EN) in('%s') order by a.STATUS desc,a.DAY_TIME desc" % (listr)
#print(query)
cur.execute(query)
for result in cur:
    print(result[0]+" - "+result[1])
cur.close()
connection.close

Xuất file pdf với python sử dụng thư viện pypdf

Do nhu cầu công việc mình cần tạo file pdf rồi gửi qua email cho mỗi người một file riêng. Trước đây để xuất tất cả dữ liệu ra 1 file pdf bằng birt report sau đó dùng tool cắt file và gửi bằng tay. Hoặc dùng birt report xuất file pdf cho từng người rồi gửi bằng tay…
Bây giờ số người cần gửi tăng lên, mình không thể gửi bằng tay như vậy được nên cần phải làm tự động thao tác này.
Bước cần làm đó là chuẩn bị cơ sở dữ liệu là excel hoặc database, sau đó dùng command line xuất file và gửi email cho từng người. Bước khó khăn đầu tiên và nhiều nhất đó là sử dụng python tự động xuất ra file pdf. Mình quyết định dùng môi trường windown và code bằng python với thư viện pypdf.

Link quan trọng để làm theo: https://www.blog.pythonlibrary.org/2018/06/05/creating-pdfs-with-pyfpdf-and-python/

Các bước quan trọng:

Bước 1: Cài python cho windown (google)
Bước 2: Cài pip cho python
Bước 3: Cài pyfpdf: python -m pip install fpdf
Bước 4: Tải và sử dụng Unicode với pyfpdf: https://pyfpdf.readthedocs.io/en/latest/Unicode/index.html
Đoạn code quan trọng để in ra được tiếng việt: pdf.add_font(‘DejaVu’, ”, ‘DejaVuSansCondensed.ttf’, uni=True)

Thành công khi kết hợp các ví dụ cơ bản trong link trên.

#!/usr/bin/python

# -*- coding: utf8 -*-

from fpdf import FPDF
 
class CustomPDF(FPDF):
 
    def header(self):
        # Set up a logo
        self.image('logo.jpg', 10, 8, 33)
        self.set_font('Arial', 'B', 10)
 
        # Add an address
        self.cell(50)
        self.cell(0, 5, 'CONG TY TNHH A VIET NAM', ln=1)
        self.cell(58)
        self.cell(0, 5, 'Dia chi: Tang 15, Thap A, Toa nha A,', ln=1)
        self.cell(60)
        self.cell(0, 5, '5321 Kim Ma, Ngoc Khanh, Ba Dinh, Ha Noi', ln=1) 
        self.cell(60)
        self.cell(0, 5, 'Tel: (+84-4) 6272 6600 -- Fax: (+84-4) 3771 4781', ln=1) 
        # Line break
        self.ln(8)
        self.cell(40)
        self.cell(0, 5, 'BANG TONG HOP CHIET KHAU THUONG MAI TREN DOANH SO', ln=1) 
        self.cell(60)
        self.cell(0, 5, 'CUA DAI LY BAN LE THANG 01/2019', ln=1) 
	
    def footer(self):
        self.set_y(-10)
 
        self.set_font('Arial', 'I', 8)
 
        # Add a page number
        page = 'Page ' + str(self.page_no()) + '/{nb}'
        self.cell(0, 10, page, 0, 0, 'C')
 
def create_pdf(pdf_path):
	data = [['','','', 'Thông tin tổng đại lý'],
			['','','Tên', 'Cong ty TNHH Thang Lai'],
			['','','Mã', '17000'],
			]
	data1 = [['STT','MA','TEN DAI LY', 'SO LUONG TB MOI','THANH TIEN(VND)'],
				['1','6501','Pham Khac Tuy rat Dep trai lai con hoc gioi', '100','45000'],
				['2','6502','ABC', '200','90000'],
				['2','6502','ABC', '200','90000'],
				['2','6502','ABC', '200','90000'],
				['3','6503','CONG TY TNHH THIET BI VA CONG NGHE NGOC ANH', '200','90000'],
				['','','', 'Tong tien gop','225000']
			]
	data4 = [['','NGUOI LAP BIEU','','KE TOAN TRUONG'],
				['','','',''],
				['','','',''],
				['','','',''],
				['','','',''],
				['','','','NGUYEN THI TO HAO']
				]			
	d2='CÔNG TY TNHH ATM VIỆT NAM'
	d1='CONG TY TNHH ATM TINH VIET NAM'
	d3='Địa chỉ: Tầng 15, Tháp A, Tòa Nhà B,'
	d31='Dia chi: Tang 15, Tháp A, Tòa Nhà B'
	pdf = FPDF()
    # Create the special value {nb}
	pdf.alias_nb_pages()
	pdf.add_page()
	pdf.set_font('DejaVu', '', 12)
	pdf.add_font('DejaVu', '', 'DejaVuSansCondensed.ttf', uni=True)
	pdf.set_font('DejaVu', '', 14)
	pdf.image('logo.jpg', x=10, y=8, w=20)
	pdf.set_font('DejaVu', '', 10)
	pdf.cell(200, 5, txt=d2, ln=1, align="C")
	pdf.set_font('DejaVu', '', 8)
	pdf.cell(200, 5, txt=d31, ln=1, align="C")
	pdf.cell(200, 5, txt="521 Kim Ma, Ngoc Khanh, Ba Dinh, Ha Noi.", ln=1, align="C")
	pdf.cell(200, 5, txt="Tel: (+84-4) 6272 6600 -- Fax: (+84-4) 3771 4781", ln=1, align="C")
	pdf.ln(8)
	pdf.set_font('DejaVu', '', 12)
	pdf.cell(200, 5, txt='BANG TONG HOP CHIET KHAU THUONG MAI TREN DOANH', ln=1, align="C")
	pdf.cell(200, 5, txt='SO CUA DAI LY BAN LE THANG 1/2019', ln=1, align="C")
	pdf.ln(8)
	pdf.set_font('DejaVu', '', 10)
	col_width = pdf.w / 4.5
	row_height = pdf.font_size
	for row in data:
		for item in row:
			pdf.cell(col_width, row_height*1,txt=item, border=0)
		pdf.ln(row_height*1)
	pdf.cell(20, 5, txt='Ngay xuat:', ln=1, align="C")
	pdf.ln(8)
	col_width = pdf.w / 5.5
	col_width1 = col_width*1/3
	col_width2 = col_width*1/3
	col_width3 = col_width+col_width*2/3+col_width*2/3
	row_height = pdf.font_size
	i=0
	for row in data1:
		i=i+1
		if i==1:
			j=0
			for item in row:
				pdf.set_font('Times', 'B', 10)
				j=j+1
				if j==1:
					pdf.cell(col_width1, row_height*1.4,txt=item, border=1,ln = 0, align = 'C', fill = False, link = '')
				else:
					if j==3:
						pdf.cell(col_width3, row_height*1.4,txt=item, border=1,ln = 0, align = 'C', fill = False, link = '')
					else:
						if j==2:
							pdf.cell(col_width2, row_height*1.4,txt=item, border=1,ln = 0, align = 'C', fill = False, link = '')
						else:
							pdf.cell(col_width, row_height*1.4,txt=item, border=1,ln = 0, align = 'C', fill = False, link = '')
		else:
			j=0
			for item in row:
				pdf.set_font('Times', '', 10)
				j=j+1
				if j==1:
					pdf.cell(col_width1, row_height*1.4,txt=item, border=1, align = 'C', fill = False)
				else:
					if j==3:
						pdf.cell(col_width3, row_height*1.4,txt=item, border=1, align = 'L', fill = False)
					else:
						if j==2:
							pdf.cell(col_width2, row_height*1.4,txt=item, border=1, align = 'C', fill = False)
						else:
							pdf.cell(col_width, row_height*1.4,txt=item, border=1, align = 'R', fill = False)
		pdf.ln(row_height*1.4)
	line_no = 1
	pdf.ln(8)
	pdf.set_font('DejaVu', '', 10)
	col_width = pdf.w / 4.5
	row_height = pdf.font_size
	for row in data4:
		for item in row:
			pdf.cell(col_width, row_height*1,txt=item, border=0)
		pdf.ln(row_height*1)
#	for i in range(50):
#		pdf.cell(0, 10, txt="Line #{}".format(line_no), ln=1)
#		line_no += 1		
	pdf.output(pdf_path)
 
if __name__ == '__main__':
    create_pdf('header_footer.pdf')