0
点赞
收藏
分享

微信扫一扫

Android(五十六):单文件、多文件 上传


展示

Android(五十六):单文件、多文件 上传_node.js

源码

服务器端

const http = require('http');
const url = require('url');
const querystring = require("querystring");
const formidable = require('formidable'); // npm install formidable
const fs = require('fs');
const path = require('path');
var util = require('util');

http.createServer((req,) => {

res.writeHead(200, {
"Content-Type": "application/json;charset=UTF-8",
"Access-Control-Allow-Origin": "*"
});

const pathname = url.parse(req.url).pathname;

// 文件上传
if (pathname === '/upload') {
const form = formidable({ multiples: true });
form.parse(req, (err, fields,) => {
try {
if (util.isArray(files.file)) {
for (let i = 0; i < files.file.length; i++) {
fs.readFile(files.file[i].filepath, (err,) => {
fs.writeFile(path.join('./', files.file[i].originalFilename), data, async (err) => {
console.log(err);
})
})
}
} else {
fs.readFile(files.file.filepath, (err,) => {
fs.writeFile(path.join('./', files.file.originalFilename), data, async (err) => {
console.log(err);
})
})
}
res.end(JSON.stringify(files));
} catch (error) {
res.end(JSON.stringify(`上传失败${Math.random()}`));
}
})
}

}).listen(8888);

console.log('Server running at http://127.0.0.1:8888/');

移动端

  • 布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="5dp">

<Button
android:id="@+id/btn_01"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorSecondary"
android:layout_marginBottom="5dp"
android:text="文件上传" />

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@color/colorSecondary"
android:layout_marginBottom="5dp">

<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
android:id="@+id/params_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="12sp"
android:padding="5dp"/>

</ScrollView>

</RelativeLayout>

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@color/colorSecondary"
android:layout_marginBottom="5dp">

<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
android:id="@+id/result_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="12sp"
android:padding="5dp"/>

</ScrollView>

</RelativeLayout>

</LinearLayout>

  • 脚本

using System.Collections.Generic;
using System.IO;
using System.Text;
using Android.App;
using Android.Content;
using Android.Net;
using Android.OS;
using Android.Provider;
using Android.Util;
using Android.Widget;
using Java.IO;
using Java.Lang;
using Java.Net;

namespace SecondaryBlankApp
{
[Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)]
public class MainActivity : Activity
{
private string TAG = "UploadFile";

// 监听请求返回
private Handler _handler;

// 请求参数View
private TextView _paramsText;

// 请求成功结果
private string _paramsStr;

// 请求结果View
private TextView _resultText;

// 请求成功结果
private byte[] _resultBytes;

protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.activity_main);

_paramsText = FindViewById<TextView>(Resource.Id.params_text);
_resultText = FindViewById<TextView>(Resource.Id.result_text);

var btn01 = FindViewById<Button>(Resource.Id.btn_01);
if (btn01 != null)
btn01.Click += delegate
{
_paramsStr = "传参:\n";
var intent = new Intent(Intent.ActionGetContent);
intent.PutExtra(Intent.ExtraAllowMultiple, true);
intent.SetType("*/*");
StartActivityForResult(intent, 1);
};

_handler = new Handler(message =>
{
switch (message.What)
{
// 请求参数
case 0:
_paramsText.Text = _paramsStr;
break;
// 请求成功
case 1:
_resultText.Text = $"返回结果:\n${Encoding.UTF8.GetString(_resultBytes)}";
break;
}
});
}

protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);

var fileList = new List<Dictionary<string, object>>();

if (data.Data != null)
{
fileList.Add(GetFileInfo(data.Data));
}
else
{
for (var i = 0; i < data.ClipData?.ItemCount; i++)
{
fileList.Add(GetFileInfo(data.ClipData.GetItemAt(i)?.Uri));
}
}

// 选择文件
if (requestCode == 1 && resultCode == Result.Ok) UploadFile(fileList);
}

private void UploadFile(List<Dictionary<string, object>> fileList)
{
new Thread(new Runnable(delegate
{
var url = new URL("http://10.10.1.184:8888/upload");
// var url = new URL("http://192.168.3.38:8888/upload");
var conn = (HttpURLConnection)url.OpenConnection();
if (conn == null) return;
conn.RequestMethod = "POST";
conn.ConnectTimeout = 60000;
conn.ReadTimeout = 60000;
conn.DoInput = true;
conn.DoOutput = true;
conn.UseCaches = false;

var outputStream = WriteFileText(conn, fileList);
_handler.SendMessage(new Message { What = 0 });

try
{
if (conn.ResponseCode != HttpStatus.Ok) return;
Log.Info(TAG, $"{TAG} ---> Success ~~~");
_resultBytes = DataToBytes(conn.InputStream);
_handler.SendMessage(new Message { What = 1 });
}
catch (Exception e)
{
Log.Info(TAG, $"{TAG} ---> Fail ~~~");
e.PrintStackTrace();
}
finally
{
outputStream.Flush();
outputStream.Close();
conn.Disconnect();
}
})).Start();
}

// 处理数据
private static byte[] DataToBytes(Stream inputStream)
{
var byteArrayOutputStream = new ByteArrayOutputStream();
var buffer = new byte[1024];
int len;
while (inputStream != null && (len = inputStream.Read(buffer)) > 0)
{
byteArrayOutputStream.Write(buffer, 0, len);
}

return byteArrayOutputStream.ToByteArray();
}

// 获取文件信息
private Dictionary<string, object> GetFileInfo(Uri uri)
{
// 文件名
var cursor = ContentResolver?.Query(uri, null, null, null, null);
var fileNameColumnIndex = cursor?.GetColumnIndex(OpenableColumns.DisplayName);
cursor?.MoveToFirst();
var fileName = cursor?.GetString((int)fileNameColumnIndex);
// 文件类型
var fileType = ContentResolver?.GetType(uri);
// 文件二进制
var inputStream = ContentResolver?.OpenInputStream(uri);
var bytes = DataToBytes(inputStream);
// 文件信息对象
var fileInfo = new Dictionary<string, object>
{
{ "name", "file" },
{ "fileName", fileName },
{ "fileType", fileType },
{ "bytes", bytes }
};
return fileInfo;
}

// 写入文件资源
DataOutputStream WriteFileText(HttpURLConnection conn, List<Dictionary<string, object>> fileList)
{
var START = "--";
var BOUNDARY = "AbCdEfGh"; // 可随机设置
var END = "\r\n";

conn.SetRequestProperty("Content-Type", $"multipart/form-data; boundary={START}{START}{BOUNDARY}");

var outputStream = new DataOutputStream(conn.OutputStream);
// 注意 outputStream.WriteBytes乱码
foreach (var fileInfo in fileList)
{
_paramsStr += $"{START}{START}{START}{BOUNDARY}{END}";
// conn.OutputStream?.Write(Encoding.UTF8.GetBytes($"{START}{START}{START}{BOUNDARY}{END}"));
outputStream.Write(Encoding.UTF8.GetBytes($"{START}{START}{START}{BOUNDARY}{END}"));
// outputStream.WriteBytes($"{START}{START}{START}{BOUNDARY}{END}");

_paramsStr += $"Content-Disposition: form-data; name=\"{fileInfo["name"]}\"; filename=\"{fileInfo["fileName"]}\"{END}";
// conn.OutputStream?.Write(Encoding.UTF8.GetBytes($"Content-Disposition: form-data; name=\"{fileInfo["name"]}\"; filename=\"{fileInfo["fileName"]}\"{END}"));
outputStream.Write(Encoding.UTF8.GetBytes($"Content-Disposition: form-data; name=\"{fileInfo["name"]}\"; filename=\"{fileInfo["fileName"]}\"{END}"));
// outputStream.WriteBytes($"Content-Disposition: form-data; name=\"{fileInfo["name"]}\"; filename=\"{fileInfo["fileName"]}\"{END}");

_paramsStr += $"Content-Type: {fileInfo["fileType"]}{END}{END}";
// conn.OutputStream?.Write(Encoding.UTF8.GetBytes($"Content-Type: {fileInfo["fileType"]}{END}{END}"));
outputStream.Write(Encoding.UTF8.GetBytes($"Content-Type: {fileInfo["fileType"]}{END}{END}"));
// outputStream.WriteBytes($"Content-Type: {fileInfo["fileType"]}{END}{END}");

_paramsStr += "===========【bytes】===========";
// conn.OutputStream?.Write((byte[])fileInfo["bytes"]);
outputStream.Write((byte[])fileInfo["bytes"]);
// outputStream.Write((byte[])fileInfo["bytes"]);

_paramsStr += $"{END}{END}";
// conn.OutputStream?.Write(Encoding.UTF8.GetBytes($"{END}{END}"));
outputStream.Write(Encoding.UTF8.GetBytes($"{END}{END}"));
// outputStream.WriteBytes($"{END}{END}");
}

_paramsStr += $"{START}{START}{START}{BOUNDARY}{START}{END}";
// conn.OutputStream?.Write(Encoding.UTF8.GetBytes($"{START}{START}{START}{BOUNDARY}{START}{END}"));
outputStream.Write(Encoding.UTF8.GetBytes($"{START}{START}{START}{BOUNDARY}{START}{END}"));
// outputStream.WriteBytes($"{START}{START}{START}{BOUNDARY}{START}{END}");

return outputStream;
}
}
}


举报

相关推荐

SpringBoot单文件上传和多文件上传

0 条评论