1. 程式人生 > >shutil模塊和幾種文件上傳Demo

shutil模塊和幾種文件上傳Demo

har app 3.3 文件信息 quest scrip struct function info

一、shutil模塊

1、介紹

shutil模塊是對os中文件操作的補充。--移動 復制 打包 壓縮 解壓

2、基本使用

1. shutil.copyfileobj(文件1, 文件2, 長度)
將文件1的數據覆蓋copy給文件2,可以copy指定大小的內容
文件1和2都是文件對象,都需要打開後才能進行復制操作

import shutil

f1 = open(testdir/1.txt, r, encoding=utf8)
f2 = open(testdir/2.txt, w, encoding=utf8)

shutil.copyfileobj(f1, f2, length
=1024) 2. shutil.copyfile(文件1,文件2) 不用打開文件,直接復制,實際上copyfile調用了copyfileobj import shutil # 1.txt必須要有,3.txt沒有就創建,有就覆蓋內容 shutil.copyfile(testdir/1.txt, testdir/3.txt) 3. shutil.copymode(文件1,文件2) 僅copy權限,不更改文件內容,組和用戶 # 先看兩個文件的權限 $ ls -l -rw-r--r-- 1 Administrator 197121 5 1月 5 10:22 1.txt
-rwxr-xr-x 1 Administrator 197121 8 1月 5 10:24 2.txt # 運行命令 import shutil shutil.copymode(testdir/1.txt, testdir/2.txt) #查看結果 $ ls -l -rw-r--r-- 1 Administrator 197121 5 1月 5 10:22 1.txt -rw-r--r-- 1 Administrator 197121 8 1月 5 10:24 2.txt 4. shutil.copystat(src,dst) 復制所有的狀態信息,包括權限,組,用戶,時間等
import shutil shutil.copystat(testdir/1.txt, testdir/2.txt) #查看結果(時間都變了) $ ls -l -rw-r--r-- 1 Administrator 197121 5 1月 5 10:22 1.txt -rw-r--r-- 1 Administrator 197121 8 1月 5 10:22 2.txt 5. shutil.copy(src,dst) 復制文件的內容以及權限,先copyfile後copymode import shutil shutil.copy(testdir/1.txt, testdir/2.txt) 6. shutil.copy2(src,dst) 復制文件的內容以及文件的所有狀態信息。先copyfile後copystat import shutil shutil.copy2(testdir/1.txt, testdir/2.txt) 7. shutil.copytree(src, dst) 遞歸的復制文件內容及狀態信息(就是拷貝整個目錄) import shutil shutil.copytree(testdir, testdir2) 結果 /testdir $ ls -l total 2 -rw-r--r-- 1 Administrator 197121 5 1月 5 10:22 1.txt -rw-r--r-- 1 Administrator 197121 8 1月 5 10:22 2.txt testdir2 $ ls -l total 2 -rw-r--r-- 1 Administrator 197121 5 1月 5 10:22 1.txt -rw-r--r-- 1 Administrator 197121 8 1月 5 10:22 2.txt 8. shutil.rmtree(path) 遞歸地刪除文件 import shutil shutil.rmtree(testdir2) 結果 testdir2目錄還在,但是裏面的文件全刪了,也就是testdir2現在是一個空文件夾 9. shutil.move(src, dst) 遞歸的移動文件 import shutil shutil.move(3.txt, testdir) # 把3.txt移動到testdir這個文件夾下 10. make_archive(base_name, format, root_dir=None) 壓縮打包 base_name:壓縮打包後的文件名或者路徑名 format: 壓縮或者打包格式 "zip", "tar", "bztar"or "gztar" root_dir : 將哪個目錄或者文件打包(也就是源文件) import shutil shutil.make_archive(E:/MyProjects/test, zip, root_dir=testdir) 把testdir這個目錄(文件也行)壓縮到E:/MyProjects目錄下,壓縮後的名字為test,格式為zip, 也就是說壓縮完成後,在E:/MyProjects下會生成一個test.zip包 11. 解壓 shutil 對壓縮包的處理是調用 ZipFile模塊來進行的 11-1、zipfile 壓縮解壓 # 壓縮 # 把testdir文件夾下的1.txt和2.txt壓縮到E:/MyProjects/test1.zip z = zipfile.ZipFile(E:/MyProjects/test1.zip, w) # 可以用 a 模塊,那麽zip包裏面可以追加內容 z.write(testdir/1.txt) z.write(testdir/2.txt) z.close() # 解壓 import zipfile z = zipfile.ZipFile(E:/MyProjects/test1.zip, r) z.extractall(E:/MyProjects/test111)#將E:/MyProjects/test1.zip解壓到E:/MyProjects/test111目錄下 # 高級應用 zipfile.is_zipfile(filename) 判斷一個文件是不是壓縮文件 ZipFile.namelist() 返回文件列表 ZipFile.open(name[, mode[, password]]) 打開壓縮文檔中的某個文件 11-2、使用shutil的內在方法解壓 shutil._unpack_zipfile(file, path) import shutil shutil._unpack_zipfile(E:/MyProjects/test1.zip, E:/MyProjects/test1) # 把E:/MyProjects/test1.zip這個zip包解壓到E:/MyProjects/test1文件夾下

二、上傳Demo

1、socket上傳文件

技術分享圖片
import json
import struct
import socketserver
import operate_handler

class MyFTP(socketserver.BaseRequestHandler):
    def handle(self):
        conn = self.request
        length = conn.recv(4)
        length = struct.unpack(i,length)[0]
        operate = (conn.recv(length)).decode(utf-8)
        operate_dic = json.loads(operate)
        opt = operate_dic[operate]
        usr = operate_dic[user]
        print(opt,usr)
        getattr(operate_handler,opt)(conn,usr)

socketserver.TCPServer.allow_reuse_address = True
server = socketserver.ThreadingTCPServer((127.0.0.1,9000),MyFTP)
server.serve_forever()
1. server.py 技術分享圖片
import os
import json
import struct

base_path = rE:\PythonProject\ftp\server\root

def upload(conn,usr):
    fileinfo_len = conn.recv(4)
    fileinfo_len = struct.unpack(i,fileinfo_len)[0]
    fileinfo = (conn.recv(fileinfo_len)).decode(utf-8)
    fileinfo = json.loads(fileinfo)
    file_path = os.path.join(base_path,usr,fileinfo[filename])
    file_path = os.path.abspath(file_path)
    with open(file_path,wb) as f:
        while fileinfo[filesize]:
            content = conn.recv(20480)
            fileinfo[filesize] -= len(content)
            f.write(content)
    print(接收完畢)
2. operate_handler.py 技術分享圖片
import os
import json
import struct
import socket

# 發送信息
def my_send(sk,operate_info):
    b_optinfo = (json.dumps(operate_info)).encode(utf-8)
    num = struct.pack(i,len(b_optinfo))
    sk.send(num)
    sk.send(b_optinfo)

sk = socket.socket()
sk.connect((127.0.0.1,9000))

# [登錄,註冊,退出]

# 要進行的操作
operate_info = {operate:upload,user:xiaoming}
my_send(sk,operate_info)

# 選擇一個文發送到server端
file_path = rF:\電影\電影\荒野生存.mp4

# 發送文件信息
file_name = os.path.basename(file_path)
file_size = os.path.getsize(file_path)
file_info = {filename:file_name,filesize:file_size}
my_send(sk,file_info)

# server端接收寫入
with open(file_path,rb) as f:
    while file_size:
        content = f.read(20480)
        file_size -= len(content)
        sk.send(content)
print(上傳完畢)
sk.close()
3. client.py

2、Django中使用form表單上傳文件

技術分享圖片
from django.shortcuts import render, HttpResponse, redirect
from django import views
import os, time
from django.conf import settings

class UploadView(views.View):

    def get(self, request):
        return render(request, upload.html)

    def post(self, request):
        # 文本類型的數據用request.POST獲取,鍵對應的值是字符串類型
        print(request.POST)
        # 文件類型的數據用request.FILES獲取,鍵對應的值是類的對象
        print(request.FILES)
        # 獲取文件對象(是一大串bytes類型的字節碼)
        file_obj = request.FILES.get(file)
        # 文件對象有個內置的屬性name,用於獲取接收到的文件名
        filename = file_obj.name
        # 判斷本地是否有同名的文件存在
        if os.path.exists(os.path.join(settings.BASE_DIR, filename)):
            # 重命名文件
            prefix_name = filename.split(.)[0]  # 前綴
            suffix_name = filename.split(.)[1]  # 後綴
            filename = prefix_name + str(time.time()) + suffix_name
        # 建一個同名的文件接收上傳的數據
        # with open(filename, ‘wb‘) as f:
        #     for i in file_obj:
        #         f.write(i)

        # 跟上面的方法是一樣的,只不過chunks是一個內置的方法,可以設置每次接收的數據大小
        with open(filename, wb) as f:
            for chunk in file_obj.chunks(chunk_size=1024):
                f.write(chunk)

        return HttpResponse(收到啦!)
        
1. views.py 技術分享圖片
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta http-equiv="content-type" charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Upload</title>
</head>

<body>

<form action="" method="post" enctype="multipart/form-data">
    {% csrf_token %}
    <p><input type="text" name="username"></p>
    <p><input type="file" name="file"></p>
    <p><input type="submit"></p>
</form>

</body>
</html>
2. HTML代碼

3、ajax文件上傳

技術分享圖片
<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="content-type" charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Upload</title>
</head>
<body>

{% csrf_token %}

<h1>上傳文件</h1>
<div>
<input type="file" id="f1">
<button id="b1"> 上傳</button>
</div>
<span style="color: red" id="s1"></span>

<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
    $(#b1).click(function () {
        // 取到要上傳的文件數據,存到一個對象中
        var fdObj = new FormData();
        fdObj.append(xx, $(#f1)[0].files[0]);
        // 在請求的數據中添加csrftokrn
        var csrfToken = $([name="csrfmiddlewaretoken"]).val();
        fdObj.append(csrfmiddlewaretoken, csrfToken);
        // 發ajax請求
        $.ajax({
            url: /upload/,
            type: post,
            data: fdObj,
            processData: false,  // 告訴jQuery不要處理我上傳的數據
            contentType: false,  // 告訴jQuery不要設置請求的文件類型,這兩個參數相當於enctype="multipart/form-data"
            success: function (res) {
                $("#s1").text(res);
            }
        })
    })
</script>
</body>
</html>
1. HTML代碼 技術分享圖片
class UploadView(views.View):
    def get(self, request):
        return render(request, upload.html)

    def post(self, request):
        file_obj = request.FILES.get(xx)
        file_name = file_obj.name
        with open(file_name, wb) as f:
            for c in file_obj.chunks():
                f.write(c)
        return HttpResponse(上傳成功!)
2. views.py

4、Flask的文件上傳並統計代碼行數

技術分享圖片
"""
app.config.root_path: 項目的根路徑
os.walk:
    遍歷你給的路徑下的所有文件(會遞歸遍歷)
    每次循環的根文件夾的路徑,文件夾的名字組成的列表,和文件組成的列表
    dirpath, dirnames, filenames
zipfile: 壓縮解壓文件的模塊
shutil: 也是壓縮解壓文件的模塊,還能移動啥的
"""

from flask import Blueprint, request, render_template
from flask import current_app as app
import shutil
from uploadCode.models import CodeRecord
from uploadCode import db
import os
import time


uploadBlue = Blueprint(uploadBlue, __name__)


# zip包上傳
@uploadBlue.route(/upload, methods=[GET, POST])
def upload():
    if request.method == "GET":
        return render_template("upload.html", error="")
    # 先獲取前端傳過來的文件
    file = request.files.get("zip_file")
    # 判斷是否是zip包
    zip_file_type = file.filename.rsplit(".", 1)
    if zip_file_type[-1] != "zip":
        return render_template("upload.html", error="文件必須是zip包")
    # 解壓路徑
    upload_path = os.path.join(app.config.root_path, "files", zip_file_type[0]+str(time.time()))
    print(upload_path)
    # 解壓前端傳過來的文件file到upload_path這個路徑
    shutil._unpack_zipfile(file, upload_path)
    # 遍歷保存的文件夾得到所有.py文件
    file_list = []
    for (dirpath, dirnames, filenames) in os.walk(upload_path):
        for filename in filenames:
            file_type = filename.rsplit(".", 1)
            if file_type[-1] != "py":
                continue
            file_path = os.path.join(dirpath, filename)
            file_list.append(file_path)
    # 打開每個文件讀取行數
    sum_num = 0
    for path in file_list:
        with open(path, mode="rb") as f:
            for line in f:
                if line.strip().startswith(b"#"):
                    continue
                sum_num += 1
    # 得到總行數去保存數據庫
    return str(sum_num)
1. upload.py 技術分享圖片
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
    請上傳你的代碼: <input type="file" name="zip_file">
    <button type="submit">提交</button>
    {{error}}
</form>


</body>
</html>
2. HTML代碼

shutil模塊和幾種文件上傳Demo