App Inventor 2 实现上传文件到服务器全方案总结

一句话结论:上传文件到服务器有 Base64 文本上传、PostFile 和云存储等方案,本页汇总各方案及前后端代码。

本文 PHP 后端已配套 Node.js 与 Python 版本,见页面中的对应实现;全部后端源码与运行说明。

« 返回首页

App Inventor 2 实现上传文件到服务器全方案总结

1、图片Base64化

图片Base64化,然后通过Web客户端POST文本的方式,发送数据,服务端base64解码后,存储文件。下载过程是Web客户端通过网络url下载文件到手机。

类似地,也可以将图片Base64化后分片存储到网络微数据库。下载过程是将分片完整合并,并解码存储到手机上。

比如,百度AI提供物品识别的API就支持待上传的图片为base64编码格式,这种方式也是较为常规的。


2、通用(二级制)文件上传:通过Web客户端POST文件

参考代码如下:

上传文件到服务器

文件成功上传并写入服务端,参考结果如下:

文件上传服务器结果


php服务端代码参考:

<?php
/* FileName: PicXfer.php
* Simple PHP script to save image file.
*/
echo "We're in the XFER Program...";//phpinfo();

$picDir = "./test/";
$fileName = $_REQUEST['pic'];

$startT = microtime(TRUE);

echo "\nReceiving: $fileName \n";
$dataToWrite = file_get_contents('php://input');

$fileStatus = file_put_contents($picDir.$fileName, $dataToWrite);
$dur = microtime(TRUE) - $startT;

echo "\nBytes written: $fileStatus \nDuration: $dur";
?>

Node.js 与 Python 的路径同为 /PicXfer.php?pic=test.png,用 PostFile 发送原始字节,返回文件名、写入字节数和耗时。文件保存在脚本旁的 test/ 目录(可用 UPLOAD_DIR 更改)。

Node.js 对应实现

保存为 pic-xfer.cjs,在文件所在目录安装依赖并启动:

npm install express@5
node pic-xfer.cjs

下载 pic-xfer.cjs

// npm install express@5
const express = require('express');
const fs = require('node:fs');
const path = require('node:path');
const app = express();
const dir = path.resolve(process.env.UPLOAD_DIR || path.join(__dirname, 'test'));
fs.mkdirSync(dir, {recursive: true});
app.post('/PicXfer.php', express.raw({type: () => true, limit: '20mb'}), (req, res) => {
  const name = String(req.query.pic || '');
  if (!name || name !== path.basename(name) || /[\\/\x00]/.test(name) || name === '..' || name === '.') {
    return res.status(400).type('text').send('错误:pic 必须是文件名');
  }
  const start = performance.now();
  const data = Buffer.isBuffer(req.body) ? req.body : Buffer.alloc(0);
  fs.writeFileSync(path.join(dir, name), data);
  res.type('text').send(`We're in the XFER Program...\nReceiving: ${name}\nBytes written: ${data.length}\nDuration: ${(performance.now() - start) / 1000}`);
});
app.use((err, req, res, next) => res.status(err.status || 500).type('text').send('错误:上传或保存失败'));
if (require.main === module) app.listen(Number(process.env.PORT || 3000), '0.0.0.0');
module.exports = app;

Python 对应实现

保存为 pic_xfer.py,在文件所在目录安装依赖并启动:

python3 -m pip install Flask
python3 pic_xfer.py

下载 pic_xfer.py

# python3 -m pip install Flask
import os
import time
from pathlib import Path
from flask import Flask, request, Response
app = Flask(__name__)
app.config['MAX_CONTENT_LENGTH'] = 20 * 1024 * 1024
DIRECTORY = Path(os.environ.get('UPLOAD_DIR', Path(__file__).parent / 'test'))
DIRECTORY.mkdir(parents=True, exist_ok=True)
@app.post('/PicXfer.php')
def receive():
    name = request.args.get('pic', '')
    if not name or name in ('.', '..') or any(c in name for c in ('/', '\\', '\0')):
        return Response('错误:pic 必须是文件名', status=400, mimetype='text/plain')
    start = time.perf_counter()
    data = request.get_data()
    try:
        (DIRECTORY / name).write_bytes(data)
    except OSError:
        return Response('错误:文件保存失败', status=500, mimetype='text/plain')
    return Response(f"We're in the XFER Program...\nReceiving: {name}\nBytes written: {len(data)}\nDuration: {time.perf_counter() - start}", mimetype='text/plain')
if __name__ == '__main__':
    app.run(host='0.0.0.0', port=int(os.environ.get('PORT', 3000)))

云服务器推荐:私有云数据库、云图片好搭档 2核2G 3M特惠主机 99元/年

原始文件上传与表单上传的区别

本文旧示例使用 PostFile,PHP 通过 php://input 读取文件原始内容。若接口通过 $_FILES 接收文件,应使用新增的 Web 客户端原生方法 PostFileWithForm(路径, 文件字段名, 表单字段)。它生成标准 multipart 表单,保留请求头鉴权和现有响应事件;附加字段在 PHP 中通过 $_POST 读取。安卓与鸿蒙支持,iOS 暂不支持。

查看积木、参数和 PHP/Node.js/Python 接收示例。

文档反馈