Android HttpConnection 文件上传

使用 HttpConnection 上传文件有点复杂,一般情况下都是用第三方库,不过,我们还是要实现一把,这样就更容易理解第三方库的某些设定

服务器端

如果使用 Servlet 开发一个服务器端比较复杂,我就直接用 GoLang 语言了

upserv.go

package main

import (
    "fmt"
    "io"
    "log"
    "net"
    "net/http"
    "os"
    "time"
)

func indexHandle(w http.ResponseWriter, r *http.Request) {
    defer func() {
        if err := recover(); err != nil {
            fmt.Println("获取页面失败")
        }
    }()

    // 上传页面
    w.Header().Add("Content-Type", "text/html")
    w.WriteHeader(200)
    html := `<!DOCTYPE html><meta charset="utf-8" />
<form id="uploadForm" enctype="multipart/form-data" action="/upload" method="POST">
<input type="file" id="file1" name="userfile" multiple /><input type="submit" value="上传">
</form>`

    io.WriteString(w, html)
}

func UploadServer(w http.ResponseWriter, r *http.Request) {

    defer func() {
        if err := recover(); err != nil {
            fmt.Println("文件上传异常")
        }
    }()

    if "POST" == r.Method {

        r.ParseMultipartForm(32 << 20)

        if r.MultipartForm != nil && r.MultipartForm.File != nil {

            fhs := r.MultipartForm.File["userfile"] //获取所有上传文件信息
            num := len(fhs)

            fmt.Printf("总文件数:%d 个文件", num)

            //循环对每个文件进行处理
            for n, fheader := range fhs {

                //获取文件名
                filename := fheader.Filename

                //结束文件
                file, err := fheader.Open()
                if err != nil {
                    fmt.Println(err)
                }

                //保存文件
                defer file.Close()
                f, err := os.Create(filename)
                defer f.Close()
                io.Copy(f, file)

                //获取文件状态信息
                fstat, _ := f.Stat()

                //打印接收信息
                fmt.Fprintf(w, "%s NO.: %d Size: %d KB Name:%s\n", time.Now().Format("2006-01-02 15:04:05"), n, fstat.Size()/1024, filename)
                fmt.Printf("%s NO.: %d Size: %d KB Name:%s\n", time.Now().Format("2006-01-02 15:04:05"), n, fstat.Size()/1024, filename)

            }
        }

        return
    } else {

        indexHandle(w, r)
    }
}

func main() {

    addrs, err := net.InterfaceAddrs()
    if err != nil {
        os.Stderr.WriteString("Oops:" + err.Error())
        os.Exit(1)
    }
    for _, a := range addrs {
        if ipnet, ok := a.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
            if ipnet.IP.To4() != nil {
                os.Stdout.WriteString(ipnet.IP.String() + "\n")
            }
        }
    }

    fmt.Println("Listening Port: 9999")
    http.HandleFunc("/", indexHandle)
    http.HandleFunc("/upload", UploadServer)
    err = http.ListenAndServe(":9999", nil)
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

把上面的代码保存为 upserv.go 然后打开终端或命令行提示符,输入以下命令直接运行

go serv.go

或者你可以下载我已经编译好的文件 /static/i/android/upserv.zip 里面有两个文件 upserv_macox 为苹果电脑下运行的,upserv_winWindows 下运行的 ,打开终端或命令行提示符,输入以下命令直接运行

upserv.exe 

成功运行后会输出以下提示

221.221.221.221
192.168.0.108
Listening Port: 9999

内网地址就是以 192.168 开头的,这时候你可以通过内网地址访问服务,比如我的 http://192.168.0.108:9999/ 运行

客户端

  1. 创建一个 空的 Android 项目 cn.twle.android.HTTPUploadFile

  2. app 上点击右键,选择 Folder - Assets Folder 创建一个 assets 目录

  3. 下载 /static/i/meimei.jpg 并且放到 assets 目录

  4. 修改 AndroidManifest.xml 中添加权限

    <!-- 往SDCard写入数据权限 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <!-- 访问internet权限 -->
    <uses-permission android:name="android.permission.INTERNET"/>
    
  5. 修改 activity_main.xml 创建布局

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical"
        android:padding="16dp">
    
        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="文件名"
            android:textSize="18sp" />
    
        <EditText
            android:id="@+id/edit_fname"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="meimei.jpg" />
    
        <Button
            android:id="@+id/btn_upload"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="上传" />
    
        <TextView
            android:id="@+id/txt_result"
            android:padding="16dp"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:gravity="center" />
    </LinearLayout>
    
  6. 创建一个上传帮助类 UploadHelper.java

    package cn.twle.android.httpuploadfile;
    
    import android.content.Context;
    
    import java.io.BufferedReader;
    import java.io.ByteArrayOutputStream;
    import java.io.DataOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.net.HttpURLConnection;
    import java.net.URL;
    
    public class UploadHelper
    {
    
        public static Boolean upload(Context context, String[] uploadFiles, String remote_url) {
    
            String end = "\r\n";
            String twoHyphens = "--";
            String boundary = "4e7050f8f4615005b4cd";
            try {
    
                URL url = new URL(remote_url);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    
                // 发送POST请求必须设置如下两行
    
                conn.setDoInput(true);
                conn.setDoOutput(true);
                conn.setUseCaches(false);
                conn.setRequestMethod("POST");
                conn.setRequestProperty("Connection", "Keep-Alive");
                conn.setRequestProperty("Charset", "UTF-8");
                conn.setRequestProperty("Content-Type","multipart/form-data;boundary=" + boundary);
    
                DataOutputStream ds =
                        new DataOutputStream(conn.getOutputStream());
                for (int i = 0; i < uploadFiles.length; i++)  {
    
                    String uploadFile  = uploadFiles[i];
    
                    File f = new File(uploadFile);
    
                    String filename = f.getName();
                    ds.writeBytes(twoHyphens + boundary + end);
                    ds.writeBytes("Content-Disposition: form-data; name=\"userfile\" ;filename=\"" +
                            filename + "\"" + end);
    
                    ds.writeBytes(end);
    
                    FileInputStream fStream = new FileInputStream(uploadFile);
                    int bufferSize = 1024;
                    byte[] buffer = new byte[bufferSize];
                    int length = -1;
                    while ((length = fStream.read(buffer)) != -1) {
                        ds.write(buffer, 0, length);
                    }
                    ds.writeBytes(end);
                    fStream.close();
                }
    
                ds.writeBytes(twoHyphens + boundary + twoHyphens + end);
                ds.flush();
                ds.close();
    
                ((MainActivity)context).sendMessage("数据发送完毕,正在等待服务器返回\n");
    
                StringBuilder sb = new StringBuilder();
    
                ByteArrayOutputStream message = new ByteArrayOutputStream();
    
                byte buffer[] = new byte[1024];
                int len = 0;
    
                if ( conn.getResponseCode() == 200 ) {
    
                    InputStream is = conn.getInputStream();
                    String mes = conn.getResponseMessage();
                    String heander = conn.getHeaderFields().toString();
    
                    while ( (len = is.read(buffer) ) != -1) {
    
                        message.write(buffer,0,len);
                    }
    
                    sb.append(new String(message.toByteArray()));
    
                    ((MainActivity) context).sendMessage(sb.toString() + "\n");
    
                    message.close();
                    is.close();
                } else {
                    ((MainActivity)context).sendMessage("服务器返回状态:" + conn.getResponseCode());
                }
                conn.disconnect();
    
            } catch (Exception e) {
    
                ((MainActivity)context).sendMessage(e.getMessage() + "\n");
            }
    
            return true;
        }
    }
    
  7. 修改 MainActivity.java

    package cn.twle.android.httpuploadfile;
    
    import android.content.Context;
    import android.os.Environment;
    import android.os.Handler;
    import android.os.Message;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    
    public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    
        private EditText edit_fname;
        private Button btn_upload;
        private TextView txt_result;
    
        private  StringBuilder sb;
    
        private String remote_url = "http://192.168.0.105:9999/upload";
    
        private Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
    
                txt_result.setText(sb.toString());
            }
        };
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            sb = new StringBuilder();
    
            //  assets 下的 python.chm 拷贝到 sd
            File root = Environment.getExternalStorageDirectory();
            File dir = new File(root.getPath() + "/assets");
    
            if ( !dir.exists()) {
                Boolean ok = dir.mkdirs();
            }
    
            String modelFilePath = "meimei.jpg";
            Assets2Sd(this, modelFilePath, dir.getPath() );
    
            edit_fname = (EditText) findViewById(R.id.edit_fname);
            btn_upload = (Button) findViewById(R.id.btn_upload);
            txt_result = (TextView) findViewById(R.id.txt_result);
    
            btn_upload.setOnClickListener(this);
        }
    
        @Override
        public void onClick(View v) {
            final String filename = edit_fname.getText().toString();
    
            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                final File file = new File(Environment.getExternalStorageDirectory().getPath() + "/assets/",filename);
                if (file.exists()) {
    
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            sendMessage("开始上传文件:" + file.getAbsolutePath() + "\n");
                            UploadHelper.upload(MainActivity.this,new String[] {file.getAbsolutePath()},remote_url);
                        }
                    }).start();
    
                } else {
                    sendMessage("文件并不存在~\n");
                }
            } else {
                sendMessage("SD卡不存在或者不可用\n");
            }
        }
    
        public void sendMessage(String msg) {
            sb.append(msg);
            handler.sendEmptyMessage(0x1001);
        }
    
        /***
         * 调用方式
         *
         * String path = Environment.getExternalStorageDirectory().toString() + "/" + "Tianchaoxiong/useso";
         String modelFilePath = "Model/seeta_fa_v1.1.bin";
         Assets2Sd(this, modelFilePath, path + "/" + modelFilePath);
         *
         * @param context
         * @param fileAssetPath assets中的目录
         * @param SdPath 要复制到sd卡中的目录
         */
        public static void Assets2Sd(Context context, String fileAssetPath, String SdPath){
            //测试把文件直接复制到sd卡中 fileSdPath完整路径
    
            String dstFile = SdPath + "/" + fileAssetPath;
            File file = new File(dstFile);
            if (!file.exists()) {
                try {
    
                    InputStream myInput;
                    OutputStream myOutput = new FileOutputStream(dstFile);
                    myInput = context.getAssets().open(fileAssetPath);
                    byte[] buffer = new byte[1024];
                    int length = myInput.read(buffer);
                    while(length > 0)
                    {
                        myOutput.write(buffer, 0, length);
                        length = myInput.read(buffer);
                    }
    
                    myOutput.flush();
                    myInput.close();
                    myOutput.close();
    
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else {
            }
    
        }
    
    }
    

Android 基础教程

关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.