客户端一:下面为 Android 客户端的实现代码:
/** * android上传文件到服务器 * * 下面为 http post 报文格式 * POST/logsys/home/uploadIspeedLog!doDefault.html HTTP/1.1 Accept: text/plain, Accept-Language: zh-cn Host: 192.168.24.56 Content-Type:multipart/form-data;boundary=-----------------------------7db372eb000e2 User-Agent: WinHttpClient Content-Length: 3693 Connection: Keep-Alive 注:上面为报文头 -------------------------------7db372eb000e2 Content-Disposition: form-data; name="file"; filename="kn.jpg" Content-Type: image/jpeg (此处省略jpeg文件二进制数据...) -------------------------------7db372eb000e2-- * * @param picPaths * 需要上传的文件路径集合 * @param requestURL * 请求的url * @return 返回响应的内容 */ public static String uploadFile(String[] picPaths, String requestURL) { String boundary = UUID.randomUUID().toString(); // 边界标识 随机生成 String prefix = "--", end = "\r\n"; String content_type = "multipart/form-data"; // 内容类型 String CHARSET = "utf-8"; // 设置编码 int TIME_OUT = 10 * 10000000; // 超时时间 try { URL url = new URL(requestURL); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setReadTimeout(TIME_OUT); conn.setConnectTimeout(TIME_OUT); conn.setDoInput(true); // 允许输入流 conn.setDoOutput(true); // 允许输出流 conn.setUseCaches(false); // 不允许使用缓存 conn.setRequestMethod("POST"); // 请求方式 conn.setRequestProperty("Charset", "utf-8"); // 设置编码 conn.setRequestProperty("connection", "keep-alive"); conn.setRequestProperty("Content-Type", content_type + ";boundary=" + boundary); /** * 当文件不为空,把文件包装并且上传 */ OutputStream outputSteam = conn.getOutputStream(); DataOutputStream dos = new DataOutputStream(outputSteam); StringBuffer stringBuffer = new StringBuffer(); stringBuffer.append(prefix); stringBuffer.append(boundary); stringBuffer.append(end); dos.write(stringBuffer.toString().getBytes()); String name = "userName"; dos.writeBytes("Content-Disposition: form-data; name=\"" + name + "\"" + end); dos.writeBytes(end); dos.writeBytes("zhangSan"); dos.writeBytes(end); for(int i = 0; i < picPaths.length; i++){ File file = new File(picPaths[i]); StringBuffer sb = new StringBuffer(); sb.append(prefix); sb.append(boundary); sb.append(end); /** * 这里重点注意: name里面的值为服务器端需要key 只有这个key 才可以得到对应的文件 * filename是文件的名字,包含后缀名的 比如:abc.png */ sb.append("Content-Disposition: form-data; name=\"" + i + "\"; filename=\"" + file.getName() + "\"" + end); sb.append("Content-Type: application/octet-stream; charset=" + CHARSET + end); sb.append(end); dos.write(sb.toString().getBytes()); InputStream is = new FileInputStream(file); byte[] bytes = new byte[8192];//8k int len = 0; while ((len = is.read(bytes)) != -1) { dos.write(bytes, 0, len); } is.close(); dos.write(end.getBytes());//一个文件结束标志 } byte[] end_data = (prefix + boundary + prefix + end).getBytes();//结束 http 流 dos.write(end_data); dos.flush(); /** * 获取响应码 200=成功 当响应成功,获取响应的流 */ int res = conn.getResponseCode(); Log.e("TAG", "response code:" + res); if (res == 200) { return SUCCESS; } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return FAILURE; }
服务端一:下面为 Java Web 服务端 servlet 的实现代码:
public class FileImageUploadServlet extends HttpServlet { private static final long serialVersionUID = 1L; private ServletFileUpload upload; private final long MAXSize = 4194304 * 2L;// 4*2MB private String filedir = null; /** * @see HttpServlet#HttpServlet() */ public FileImageUploadServlet() { super(); // TODO Auto-generated constructor stub } /** * 设置文件上传的初始化信息 * * @see Servlet#init(ServletConfig) */ public void init(ServletConfig config) throws ServletException { FileItemFactory factory = new DiskFileItemFactory();// Create a factory // for disk-based // file items this.upload = new ServletFileUpload(factory);// Create a new file upload // handler this.upload.setSizeMax(this.MAXSize);// Set overall request size // constraint 4194304 filedir = config.getServletContext().getRealPath("images"); System.out.println("filedir=" + filedir); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse * response) */ @SuppressWarnings("unchecked") protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub PrintWriter out = response.getWriter(); try { // String userName = request.getParameter("userName");//获取form // System.out.println(userName); List<FileItem> items = this.upload.parseRequest(request); if (items != null && !items.isEmpty()) { for (FileItem fileItem : items) { String filename = fileItem.getName(); if (filename == null) {// 说明获取到的可能为表单数据,为表单数据时要自己读取 InputStream formInputStream = fileItem.getInputStream(); BufferedReader formBr = new BufferedReader(new InputStreamReader(formInputStream)); StringBuffer sb = new StringBuffer(); String line = null; while ((line = formBr.readLine()) != null) { sb.append(line); } String userName = sb.toString(); System.out.println("姓名为:" + userName); continue; } String filepath = filedir + File.separator + filename; System.out.println("文件保存路径为:" + filepath); File file = new File(filepath); InputStream inputSteam = fileItem.getInputStream(); BufferedInputStream fis = new BufferedInputStream(inputSteam); FileOutputStream fos = new FileOutputStream(file); int f; while ((f = fis.read()) != -1) { fos.write(f); } fos.flush(); fos.close(); fis.close(); inputSteam.close(); System.out.println("文件:" + filename + "上传成功!"); } } System.out.println("上传文件成功!"); out.write("上传文件成功!"); } catch (FileUploadException e) { e.printStackTrace(); out.write("上传文件失败:" + e.getMessage()); } } }
客户端二:下面为用 .NET 作为客户端实现的 C# 代码:
/** 下面为 http post 报文格式 POST/logsys/home/uploadIspeedLog!doDefault.html HTTP/1.1 Accept: text/plain, Accept-Language: zh-cn Host: 192.168.24.56 Content-Type:multipart/form-data;boundary=-----------------------------7db372eb000e2 User-Agent: WinHttpClient Content-Length: 3693 Connection: Keep-Alive 注:上面为报文头 -------------------------------7db372eb000e2 Content-Disposition: form-data; name="file"; filename="kn.jpg" Content-Type: image/jpeg (此处省略jpeg文件二进制数据...) -------------------------------7db372eb000e2-- * * */ private STATUS uploadImages(String uri) { String boundary = "------------Ij5ei4ae0ei4cH2ae0Ef1ei4Ij5gL6";; // 边界标识 String prefix = "--", end = "\r\n"; /** 根据uri创建WebRequest对象**/ WebRequest httpReq = WebRequest.Create(new Uri(uri)); httpReq.Method = "POST";//方法名 httpReq.Timeout = 10 * 10000000;//超时时间 httpReq.ContentType = "multipart/form-data; boundary=" + boundary;//数据类型 /*******************************/ try { /** 第一个数据为form,名称为par,值为123 */ StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(prefix); stringBuilder.Append(boundary); stringBuilder.Append(end); String name = "userName"; stringBuilder.Append("Content-Disposition: form-data; name=\"" + name + "\"" + end); stringBuilder.Append(end); stringBuilder.Append("zhangSan"); stringBuilder.Append(end); /*******************************/ Stream steam = httpReq.GetRequestStream();//获取到请求流 byte[] byte8 = Encoding.UTF8.GetBytes(stringBuilder.ToString());//把form的数据以二进制流的形式写入 steam.Write(byte8, 0, byte8.Length); /** 列出 G:/images/ 文件夹下的所有文件**/ DirectoryInfo fileFolder = new DirectoryInfo("G:/images/"); FileSystemInfo[] files = fileFolder.GetFileSystemInfos(); for(int i = 0; i < files.Length; i++) { FileInfo file = files[i] as FileInfo; stringBuilder.Clear();//清理 stringBuilder.Append(prefix); stringBuilder.Append(boundary); stringBuilder.Append(end); /** * 这里重点注意: name里面的值为服务器端需要key 只有这个key 才可以得到对应的文件 * filename是文件的名字,包含后缀名的 比如:abc.png */ stringBuilder.Append("Content-Disposition: form-data; name=\"" + i + "\"; filename=\"" + file.Name + "\"" + end); stringBuilder.Append("Content-Type: application/octet-stream; charset=utf-8" + end); stringBuilder.Append(end); byte[] byte2 = Encoding.UTF8.GetBytes(stringBuilder.ToString()); steam.Write(byte2, 0, byte2.Length); FileStream fs = new FileStream(file.FullName, FileMode.Open, FileAccess.Read);//读入一个文件。 BinaryReader r = new BinaryReader(fs);//将读入的文件保存为二进制文件。 int bufferLength = 8192;//每次上传8k; byte[] buffer = new byte[bufferLength]; long offset = 0;//已上传的字节数 int size = r.Read(buffer, 0, bufferLength); while (size > 0) { steam.Write(buffer, 0, size); offset += size; size = r.Read(buffer, 0, bufferLength); } /** 每个文件结束后有换行 **/ byte[] byteFileEnd = Encoding.UTF8.GetBytes(end); steam.Write(byteFileEnd, 0, byteFileEnd.Length); fs.Close(); r.Close(); } byte[] byte1 = Encoding.UTF8.GetBytes(prefix + boundary + prefix + end);//文件结束标志 steam.Write(byte1, 0, byte1.Length); steam.Close(); WebResponse response = httpReq.GetResponse();// 获取响应 Console.WriteLine(((HttpWebResponse)response).StatusDescription);// 显示状态 steam = response.GetResponseStream();//获取从服务器返回的流 StreamReader reader = new StreamReader(steam); string responseFromServer = reader.ReadToEnd();//读取内容 Console.WriteLine(responseFromServer); // 清理流 reader.Close(); steam.Close(); response.Close(); return STATUS.SUCCESS; } catch (System.Exception e) { Console.WriteLine(e.ToString()); return STATUS.FAILURE; } }
服务端二: 下面为 .NET 实现的服务端 C# 代码:
protected void Page_Load(object sender, EventArgs e) { string userName = Request.Form["userName"];//接收form HttpFileCollection MyFilecollection = Request.Files;//接收文件 for (int i = 0; i < MyFilecollection.Count; i++ ) { MyFilecollection[i].SaveAs(Server.MapPath("~/netUploadImages/" + MyFilecollection[i].FileName));//保存图片 } }