当前位置: 首页>移动开发>正文

自己动手实现自动打包,上传下载服务,前端展示

前段时间,独自接手公司另一个项目组的App(该产品仅存的唯一的一个小伙伴离职了),本来心里很不情愿。因为代码实在是太古老了,而且经过了n手的像我这样的断代接收,长期处于半维护状态,所以我都是一边看代码一边吐槽。并不是说前面的小伙伴的技术不好,而是经过多年多次流转,每一代都风格迥异就形成了现在这副冗余不堪的样子。

我们自己的App是用当前最流行的Jenkins+Git+Gradle持续集成,但这个App就惨了,你不得不自己打包发到群里,可想而知多少麻烦,就想着接入接入我们的Jenkins服务器,自动打包。但是被权限问题折腾过后,而且这段时间大家都忙着一个超高优先级的项目,就先搁置了。

前天就想着为什么不自己写一套呢。反正有免费的服务器用,那就物尽其用。

首先要实现的功能:
1,自动打包-Python实现
2,文件上传下载服务器-Python实现
3,包列表前端展示-HTML
4,包列表展示和下载移动端实现

经过两天的加班加点,终于实现啦,先看效果:
移动端apk列表:


自己动手实现自动打包,上传下载服务,前端展示,第1张
移动端

前端apk列表:


自己动手实现自动打包,上传下载服务,前端展示,第2张
前端

后端文件服务核心代码:

import os

from flask import request, jsonify
from flask import send_from_directory, abort
from flask_restful import Resource, reqparse
from werkzeug.utils import secure_filename

from modules.APKRecord import APKRecordModel
from support.CHelper import get_millisecond, get_file_name

basedir = os.path.abspath(os.path.dirname(__file__))
# set(['jpeg', 'apk'])
ALLOWED_EXTENSIONS = {'apk'}


# 用于判断文件后缀
def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS


class APKRecord(Resource):
    @staticmethod
    def get():
        return {"You should have a file_name": 404}, 403

    # @staticmethod
    # def get(file_name):
    #     if os.path.isfile(os.path.join('uploadApk', file_name)):
    #         return send_from_directory('uploadApk', file_name, as_attachment=True)
    #     abort(404)

    @staticmethod
    def get(file_name):
        if os.path.isfile(os.path.join(r'D:\_pythonProj\CFlaskProj\resources\uploadApk', file_name)):
            return send_from_directory(r'D:\_pythonProj\CFlaskProj\resources\uploadApk', file_name, as_attachment=True)
        else:
            abort(404)


class APKRecordList(Resource):
    parser = reqparse.RequestParser()

    @staticmethod
    def get():
        file_dir = os.path.join(basedir, "uploadApk")
        if not os.path.exists(file_dir):
            os.makedirs(file_dir)

        apkList = []
        if os.path.exists(file_dir):
            for root, dirs, files in os.walk(file_dir):
                for file in files:
                    item = APKRecordModel(file)
                    apkList.append(item.json())

        return jsonify(result='success', data=apkList)

    def post(self):
        file_dir = os.path.join(basedir, "uploadApk")
        if not os.path.exists(file_dir):
            os.makedirs(file_dir)
        f = request.files['apk_name']  # 从表单的file字段获取文件,apk_name为该表单的name值
        if f and allowed_file(f.filename):  # 判断是否是允许上传的文件类型
            fname = secure_filename(f.filename)
            ext = fname.rsplit('.', 1)[1]  # 获取文件后缀
            name = get_file_name(fname)
            timestamp = get_millisecond()
            new_filename = name + '_' + str(timestamp) + '.' + ext  # 修改了上传的文件名加上了 _时间戳
            f.save(os.path.join(file_dir, new_filename))  # 保存文件到uploadApk目录
            return {"code": 0, "msg": "upload success", "fileName": new_filename, "fileTime": timestamp}, 201
        else:
            return {"code": 1001, "msg": "file not allowed"}

这里要注意的一点的是:不同的环境(比如Mac环境和Windows环境),这个地址也要改变:
Mac环境下:

    @staticmethod
    def get(file_name):
        if os.path.isfile(os.path.join('uploadApk', file_name)):
            return send_from_directory('uploadApk', file_name, as_attachment=True)
        abort(404)

Windows环境下:

    @staticmethod
    def get(file_name):
        if os.path.isfile(os.path.join(r'D:\_pythonProj\CFlaskProj\resources\uploadApk', file_name)):
            return send_from_directory(r'D:\_pythonProj\CFlaskProj\resources\uploadApk', file_name, as_attachment=True)
        else:
            abort(404)

前端展示:还是用的最简单jquery

<script>
  $.ajax({
    url: "/apk/records",
    dataType: 'json',
    success: function (res) {
      res.data.map(item => {
        let liNode = document.createElement("li");
        liNode.className = "my_record_list_li"

        let labelNode = document.createElement("label")
        labelNode.className = "my_record_list_label"
        let spanNode = document.createElement("span")
        spanNode.innerHTML = item.fileTime
        labelNode.append(spanNode)
        let delNode = document.createElement("a");
        delNode.className = "delete_record"
        delNode.href = item.downloadUrl
        delNode.innerHTML = "下载"
        labelNode.append(delNode)

        let aNode = document.createElement("a");
        aNode.className = "my_record_list_a"
        aNode.href = item.downloadUrl
        aNode.innerHTML = item.fileName

        liNode.append(aNode)
        liNode.append(labelNode)

        $("#record_list_container").append(liNode)
      })
      document.getElementById('record_num_value').innerHTML = "共" + res.data.length + "个包"
    }
  })

</script>

同样实现了,通过网页上传代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文件上传</title>

</head>
<body>
<form id="form1" method="post" action="http://xx.xxxx.xxxx.xxxx:5000/apk/records" enctype="multipart/form-data">
    <div>
        <input id="file1" type="file" name="apk_name"/>
        <input type="submit">提交</input>
    </div>
</form>
</body>
</html>

当然打包,上传脚本核心代码:


# 请求服务器
def request_url(url, params):
    cookies = cookielib.CookieJar()
    opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookies), MultipartPostHandler.MultipartPostHandler)
    try:
        print('request url:' + url)
        print('request params:' + str(params))
        response = opener.open(url, params)
        return response.read()
    except Exception as e:
        print(str(e))


# 上传文件到服务器
def upload_file(url, apkpath):
    params = {'username': reinforce_username, 'password': reinforce_password, 'apk': open(apkpath, 'rb'),
              'tactics_id': reinforce_tactics_id}
    response = request_url(url, params)
    data = json.loads(response)
    return data

搞定这些东西还是有点成就感的,感觉应该可以写成gradle脚本,甚至生成gradle插件,这样服务器就没必要配置Python环境,稍后有时间写成插件。


https://www.xamrdz.com/mobile/4hj1876023.html

相关文章: