您现在的位置是:首页 >技术教程 >asp.net建立一个带验证的上传文件接口然后用安卓程序和微信小程序上传文件网站首页技术教程
asp.net建立一个带验证的上传文件接口然后用安卓程序和微信小程序上传文件
安卓app和微信小程序上传小文件是常见的功能,下面我用asp.net写一个接口,并且模拟这个接口只能在验证特定用户身份后才上传文件。然后分别用微信开发者工具写一个微信小程序、Android Studio写一个app,实现上传小文件功能。根据不同开发工具,代码分为三部份,第一个是asp.net接口。
打开或新建一个网站,在“解决方案资源窗口”右键添加一个文件夹,取名upload,用于存放上传的文件,再添加一个类取名UpLoad,它将被封装成JSON用于告诉调用接口者文件是否上传的相关信息。在UpLoad添加几个公有变量。它们分别是:
filename,类型string,如果文件上传成功,会显示存储到服务器的文件名,上传失败则返回空的字符串。
ext,类型string 如果文件上传成功,会显示存储到服务器的文件名扩展名,上传失败则返回空的字符串。
iscorrect,类型bool,文件上传为true,反之为false。
tip 类型string,如果文件上传成功显示“上传成功”,反之显示相应错误信息。代码如下
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
/// <summary>
///UpLoad 的摘要说明
/// </summary>
public class UpLoad
{
public string filename;
public string ext;
public bool iscorrect;
public string tip;
public UpLoad()
{
//
//TODO: 在此处添加构造函数逻辑
//
filename = "";
ext = "";
iscorrect = true;
tip = "";
}
}
然后我们继续在“解决方案资源窗口”右键添加一个“一般处理程序”(扩展名ashx),此处取名为UploadFileAndLoginHandler。这里必须模拟用户名必须是admin才能上传文件,代码如下
<%@ WebHandler Language="C#" Class="UploadFileAndLoginHandler" %>
using System;
using System.Web;
using System.IO;
using Newtonsoft.Json;
public class UploadFileAndLoginHandler : IHttpHandler {
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
UpLoad XUpload = new UpLoad();
if (context.Request.Params["username"] == null)
{
XUpload.filename = "";
XUpload.ext = "";
XUpload.iscorrect = false;
XUpload.tip = "必须输入用户名";
string result = JsonConvert.SerializeObject(XUpload);
context.Response.Write(result);
return;
}
if (context.Request.Params["username"].ToString() != "admin")
{
XUpload.filename = "";
XUpload.ext = "";
XUpload.iscorrect = false;
XUpload.tip = "用户名不正确";
string result = JsonConvert.SerializeObject(XUpload);
context.Response.Write(result);
return;
}
try
{
if (context.Request.Files.Count > 0)
{
HttpPostedFile file = context.Request.Files["upload_file"];
string filename = Path.GetFileNameWithoutExtension(file.FileName);
string ext = Path.GetExtension(file.FileName);
string newfilename = DateTime.Now.Ticks.ToString() + ext;
string filePath = context.Server.MapPath("upload/") + newfilename;
file.SaveAs(filePath);
XUpload.filename = newfilename;
XUpload.ext = ext;
XUpload.iscorrect = true;
XUpload.tip = "";
// context.Response.Write("Yes");
}
else
{
XUpload.filename = "";
XUpload.ext = "";
XUpload.iscorrect = false;
XUpload.tip = "请上传文件";
// context.Response.Write("No");
}
}
catch (Exception ex)
{
XUpload.filename = "";
XUpload.ext = "";
XUpload.iscorrect = false;
XUpload.tip = ex.Message;
}
finally
{
string result = JsonConvert.SerializeObject(XUpload);
context.Response.Write(result);
}
}
public bool IsReusable {
get {
return false;
}
}
}
运行代码,记下接口地址。至此,我们服务端代码就完成了。现在是第二块,编写微信小程序,使用微信开发者工具新建或打开一个小程序项目,注意因为在自己电脑测试,所以在要开发工具右侧详情->本地设置中勾选不校验合法域名,如图。
添加一个page,注意将接口地址替换成你自己的。wxml代码如下
<!--pages/index/index.wxml-->
<button type="primary" bind:tap="chooseImg">选择图片</button>
<button type="primary" bind:tap="uploadimg">上传图片</button>
js代码如下,注意将接口地址替换成你自己的。
// pages/index/index.js
Page({
/**
* 页面的初始数据
*/
data: {
src: '' //上传图片的路径地址
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
},
chooseImg() {
var that = this
wx.chooseImage({
count: 1, // 默认9
sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
success: function (res) {
// 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片
let src = res.tempFilePaths[0]
that.setData({ src: src })
}
})
},
uploadimg()
{
var that = this
//获取图片路径地址
let src = this.data.src
//尚未选择图片
if (src == '') {
wx.showToast({
title: '请先选择文件!',
icon: 'none'
})
}
//准备上传文件
else {
//发起文件上传请求http://localhost/miniDemo/upload.php
var uploadTask = wx.uploadFile({
url: 'http://localhost:56360/UploadFileAndLoginService/UploadFileAndLoginHandler.ashx', //可以替换为开发者自己的服务器地址
filePath: src,
name: 'upload_file',
formData:{
username:"admin"
},
success: function (res) {
console.log(res)
wx.showToast({
title: res.data
})
}
})
}
}
})
运行模拟器,上传一张图片,如果json字符串出现图片名,并且不是空字符串,则表明上传成功,进入网站的upload的目录,可以看到刚上传的图片,我们可以试着将上面代码formData中用username的admin,替换成其它名称,然后重新运行小程序,再上传图片,发现上传失败,tip显示“用户名不正确”的提示,起到了上传前验证用户身份的功能。至此,微信小程序端代码也完成了。注意,偷懒期间,这里示例中只是输出了json字符串,实际应用中应解析json字符串,然后根据需求为UI赋值。
最后一块是安卓app。打开或新建一个项目,如果条件受限只能是本地测试,我们便要在avd模拟器中的的相册中放一些图片,用于一会之后上传测试,所以先不急着编写代码而直接运行avd模拟器,然后在view菜单下如图打开模拟器的“文件浏览器”,在mnt->sdcard->DCIM上右键上传一些图片到模拟器,然后重启模拟器,这样们就可以打开相册选择图片,当然如果是真机连接,此步可省略(图片容量不要太大)。
首先,打开AndroidManifest添加网络访问、文件读写等权限,因为是在自己电脑上测试,所以要在application节点添加android:usesCleartextTraffic=“true”,因为AS默认只能访问https、wss等有ssl协议的网址,添加此属性后,可解除此限制。
完成后将左侧导航栏切换到project视图,如图在libs下添加第三个包。然后打开build.gradle根节点添加
repositories {
flatDir{
dirs(‘libs’)
}
}
接着在dependencies添加implementation files(‘libsokhttp-3.2.0.jar’)、api(name: ‘WaitDialog’,ext: ‘aar’)、implementation files(‘libsokio-1.9.0.jar’)。
下面是布局代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/Btn"
android:text="上传文件"/>
</LinearLayout>
布局代码写完后,便是java代码了,因为安卓不允许在主线程中进行访问网络等耗时操作,所以要通过分线程来访问,所以代码比微信小程序要复杂许多,上代码,注意如果是本地调试,接口地址栏的ip不是127.0.0.1,也不是localhost,而是10.0.2.2。
package person.yinzhenwei.loginanduploadtoaspnet;
import androidx.appcompat.app.AppCompatActivity;
import android.Manifest;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
import java.util.Calendar;
import java.util.UUID;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import person.yinzhenwei.loginanduploadtoaspnet.util.PermessionUtil;
import swaddle.yinzhenwei.waitdialog.WaitDialog;
public class MainActivity extends AppCompatActivity implements View.OnClickListener
{
private static String[] PERMISSIONS = {
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.MANAGE_EXTERNAL_STORAGE
};
private WaitDialog waitDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PermessionUtil.CheckPermissions(this,PERMISSIONS,1);
setContentView(R.layout.activity_main);
waitDialog=new WaitDialog(this);
findViewById(R.id.Btn).setOnClickListener(this);
}
private ResponseBody upload(String url, String filePath, String fileName) throws Exception
{
OkHttpClient client = new OkHttpClient();
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)//file
.addFormDataPart("upload_file", fileName,
RequestBody.create(MediaType.parse("multipart/form-data"), new File(filePath)))
.addFormDataPart("username","admin")
.build();
Request request = new Request.Builder()
.header("Authorization", "Client-ID " + UUID.randomUUID())
.url(url)
.post(requestBody)
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
return response.body();
}
private void uploadtojavaweb(String UploadFilename)
{
Calendar calendar=Calendar.getInstance();
Message message = Message.obtain(); // 获得一个默认的消息对象
String ext=GetExt(UploadFilename);
String fileName=String.valueOf(calendar.getTimeInMillis())+"."+ext;
//http://10.0.2.2:1994/firstweb/UploadHandleServlet
String url = "http://10.0.2.2:56360/UploadFileAndLoginService/UploadFileAndLoginHandler.ashx";
try
{
//
String str=upload(url, UploadFilename, fileName).string();
Log.v("yzw",str);
message.obj=str;
}
catch (Exception e)
{
Log.v("yzw",e.toString());
message.obj=e.toString();
}
mHandler.sendMessage(message);
}
private void openalbum()
{
Intent albumIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
//albumIntent.addCategory(Intent.CATEGORY_OPENABLE);
albumIntent.setType("image/*"); // 类型为图像
startActivityForResult(albumIntent, 100); // 打开系统相册
}
private String uri2Path(Uri uri) //将URi转为路径
{
int actual_image_column_index;
String img_path;
String[] proj = { MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(uri, proj, null, null, null);
actual_image_column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
img_path = cursor.getString(actual_image_column_index);
return img_path;
}
private String GetExt(String FileName) //获得扩展名
{
String result="";
if (FileName.length()>0)
{
String[] arrext=FileName.split("\.");
if (arrext.length>0)
{
result=arrext[arrext.length-1];
}
else
{
result="";
}
}
return result;
}
private Handler mHandler = new Handler()
{
public void handleMessage(Message msg)
{
String tip=String.valueOf(msg.obj);
if (tip.length()>0) {
Toast.makeText(MainActivity.this, tip, Toast.LENGTH_LONG).show();
}
waitDialog.dismiss();
}
};
@Override
public void onClick(View view)
{
openalbum();
}
protected void onActivityResult(int requestCode, int resultCode, Intent intent)
{
super.onActivityResult(requestCode, resultCode, intent);
switch (requestCode)
{
case 100:
Uri uri = intent.getData(); // 获得已选择照片的路径对象
String FileName=uri2Path(uri);
TUpload tupload=new TUpload();
tupload.FileName=FileName;
waitDialog.show();
waitDialog.setText("正将文件上传到服务器,稍候");
tupload.start();
break;
}
}
private class TUpload extends Thread
{
public String FileName="";
public void run()
{
uploadtojavaweb(FileName);
}
}
}
运行,打开相册上传一张图片,如果json字符串出现图片名,并且不是空字符串,则表明上传成功,进入网站的upload的目录,可以看到刚上传的图片,我们可以在requestBody.addFormDataPart中的username中的admin替换,然后重新运行app,再上传图片,发现上传失败,tip显示“用户名不正确”的提示,起到了上传前验证用户身份的功能。至此,app端代码也完成了。注意,偷懒期间,这里示例中只是输出了json字符串,实际应用中应解析json字符串,然后根据需求为UI赋值。
写的好辛苦,阅读完后点个赞再走呗,源码在评论中后附。