最近在弄一个项目,需要用到android拍照图片上传到LAMP服务器中去,网上找了很多代码,都不能实现上传文件,原因是当时使用的租用虚拟主机空间,文章是这么说的:
写道
通过前一篇转载的博文,已经可以实现上传图片、文件等。不过当时是在本地服务器,当我将PHP代码放到租用的虚拟主机的时候,就出现问题了。我POST请求在服务器那边获取不到任何数据。也就是说 $_POST 和 &_FILES 都是空的。而测试POST到本地的服务器,又很正常。这就很奇怪了。
为了确实是什么问题,我是这么做的:
我写了一个HTML的form表单,提交到远程服务器上,没问题。
然后用Fiddler抓包软件,抓取HTML的表单请求包和Android发送的请求包,对比。看看有什么不一样。
最后发现,在请求包里有Transfer-Encoding: chunked的时候,服务器就获取不到参数。
当没有Transfer-Encoding: chunked而有Content-Length: xxx的时候就没问题然后回头看看Android的代码,将
//这句注释掉。并记录整个请求包的大小,设置一下
//httpURLConnection.setChunkedStreamingMode(128 * 1024);
httpURLConnection.setRequestProperty("Content-Length", ""+Data.length);就好了。
不知道为什么租用的虚拟主机不支持,害得我调试了好久。还有之前的RSA生成、长链接的实现,都受虚拟主机限制的影响。
Transfer-Encoding: chunked 表示使用分块传输编码这一机制,只在 HTTP1.1里才有。
可以不事先确定整个Request包的大小,而是将数据分块发送。
在Body中就是 一个十六进制的数字表示接下来的包的长度,然后包的内容
Request的结束就是当分块包的长度为0。比如:
HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked
25
This is the data in the first chunk
1C
and this is the second one
3
con
8
sequence
0
(转发请注明转自:学PHP)
为了确实是什么问题,我是这么做的:
我写了一个HTML的form表单,提交到远程服务器上,没问题。
然后用Fiddler抓包软件,抓取HTML的表单请求包和Android发送的请求包,对比。看看有什么不一样。
最后发现,在请求包里有Transfer-Encoding: chunked的时候,服务器就获取不到参数。
当没有Transfer-Encoding: chunked而有Content-Length: xxx的时候就没问题然后回头看看Android的代码,将
//这句注释掉。并记录整个请求包的大小,设置一下
//httpURLConnection.setChunkedStreamingMode(128 * 1024);
httpURLConnection.setRequestProperty("Content-Length", ""+Data.length);就好了。
不知道为什么租用的虚拟主机不支持,害得我调试了好久。还有之前的RSA生成、长链接的实现,都受虚拟主机限制的影响。
Transfer-Encoding: chunked 表示使用分块传输编码这一机制,只在 HTTP1.1里才有。
可以不事先确定整个Request包的大小,而是将数据分块发送。
在Body中就是 一个十六进制的数字表示接下来的包的长度,然后包的内容
Request的结束就是当分块包的长度为0。比如:
HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked
25
This is the data in the first chunk
1C
and this is the second one
3
con
8
sequence
0
(转发请注明转自:学PHP)
贴上代码:
package com.uploaddemo.control; import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import org.apache.http.HttpStatus; import org.apache.http.ProtocolException; import android.content.Context; import android.util.Log; public class UploadHelper { private static final String TAG = "salesman"; private Context context = null; private String serverUrl = null; private String param1 = null; private String param2 = null; private String filePath = null; private String fileName = null; private static final int DEFAULT_BUFF_SIZE = 8192; private static final int READ_TIMEOUT = 15000; private static final int CONNECTION_TIMEOUT = 15000; private UploadListener uploadListener = null; public UploadHelper(Context context, String url, String param1, String param2, String filePath, String fileName) { this.context = context; this.serverUrl = url; this.param1 = param1; this.param2 = param2; this.filePath = filePath; this.fileName = fileName; } public void setUploadListener(UploadListener listener) { this.uploadListener = listener; } public void uploadFile() throws MalformedURLException, ProtocolException, FileNotFoundException, IOException { String lineEnd = "\r\n"; String twoHyphens = "--"; String boundary = "--------------et567z";// 各个参数的间隔符,可自定义,但不能与发送内容有重复部分 if (context == null || serverUrl == null || param1 == null || param2 == null || filePath == null || fileName == null) { return; } URL url = new URL(serverUrl); HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection(); // 设置每次传输的流大小,可以有效防止手机因为内存不足崩溃 // 此方法用于在预先不知道内容长度时启用没有进行内部缓冲的 HTTP 请求正文的流。 // 租用的服务器空间这里必须去掉否则服务器接收不了任何参数 //httpURLConnection.setChunkedStreamingMode(128 * 1024);// 128K //httpURLConnection.setRequestProperty("Content-Length", ""+ 1024 * 1024); // 允许输入输出流 httpURLConnection.setDoInput(true); httpURLConnection.setDoOutput(true); httpURLConnection.setUseCaches(false); // 超时时间设置 httpURLConnection.setReadTimeout(READ_TIMEOUT); httpURLConnection.setConnectTimeout(CONNECTION_TIMEOUT); // 使用POST方法 httpURLConnection.setRequestMethod("POST"); httpURLConnection.setRequestProperty("Connection", "Keep-alive"); httpURLConnection.setRequestProperty("Charset", "UTF-8"); httpURLConnection.setRequestProperty("Content-Type", "Multipart/form-data;boundary=" + boundary); DataOutputStream dos = new DataOutputStream(httpURLConnection.getOutputStream()); // 发送jsonStr dos.writeBytes(twoHyphens + boundary + lineEnd); dos.writeBytes("Content-Disposition: form-data; name=\"param1\"" + lineEnd); dos.writeBytes(lineEnd); dos.writeBytes(param1); dos.writeBytes(lineEnd); // 发送acrion dos.writeBytes(twoHyphens + boundary + lineEnd); dos.writeBytes("Content-Disposition: form-data; name=\"param2\"" + lineEnd); dos.writeBytes(lineEnd); dos.writeBytes(param2); dos.writeBytes(lineEnd); // 发送文件 dos.writeBytes(twoHyphens + boundary + lineEnd); dos.writeBytes("Content-Disposition: form-data; name=\"uploadedfile\"; filename=\"" + fileName + "\"" + lineEnd); dos.writeBytes(lineEnd); //dos.writeBytes("Content-Type: image/*\r\n\r\n"); String srcPath = filePath + fileName; FileInputStream fis = new FileInputStream(srcPath); byte[] buffer = new byte[DEFAULT_BUFF_SIZE]; // 8k int counter = 0; int count = 0; // 读取文件 while ((count = fis.read(buffer)) != -1) { dos.write(buffer, 0, count); counter += count; if (uploadListener != null) { uploadListener.onUploadProcess(counter); } } fis.close(); dos.writeBytes(lineEnd); dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);// 最后多出"--"作为结束 dos.flush(); if (httpURLConnection.getResponseCode() == HttpStatus.SC_OK) { BufferedReader reader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream()), 8192);// 8k StringBuilder sb = new StringBuilder(); String line = null; try { while ((line = reader.readLine()) != null) { sb.append(line + "\n"); } } catch (IOException e) { e.printStackTrace(); } if (uploadListener != null) { uploadListener.onUploadFinished(sb.toString()); } Log.e("salesman", "show........."); } else { Log.e(TAG, "Http request failed!"); if (uploadListener != null) { uploadListener.onUploadFinished("Http request failed!"); } } if (httpURLConnection != null) { httpURLConnection.disconnect(); } } }
package com.uploaddemo.control; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.net.MalformedURLException; import java.net.ProtocolException; import android.app.Activity; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; public class UploadDemoActivity extends Activity { private TextView txtVServerUrl = null; private TextView txtVFilePath = null; private Button btnUpload = null; private ProgressBar progressBar = null; private String filePath = Environment.getExternalStorageDirectory() + "/salesman/"; private String fileName = "test.jpg"; private String serverUrl = "http://www.bocn.com/upload.php"; private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { if (msg.what == 0) { progressBar.setProgress(msg.arg1); } else if (msg.what == 1) { Bundle b = msg.getData(); if (b == null) { return; } String str = b.getString("msg"); Toast.makeText(UploadDemoActivity.this, str, Toast.LENGTH_LONG).show(); } } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); txtVServerUrl = (TextView) findViewById(R.id.ID_TxtV_ServerUrl); txtVServerUrl.setText("serverUrl:" + serverUrl); txtVFilePath = (TextView) findViewById(R.id.ID_TxtV_FilePath); txtVFilePath.setText("filePath:" + filePath + fileName); progressBar = (ProgressBar) findViewById(R.id.ID_PBar); File file = new File(filePath, fileName); progressBar.setMax((int) file.length()); btnUpload = (Button) findViewById(R.id.ID_Btn_Upload); btnUpload.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { final UploadHelper UploadHelper = new UploadHelper(UploadDemoActivity.this, serverUrl, "heihei", "haha", filePath, fileName); UploadHelper.setUploadListener(new UploadListener() { @Override public void onUploadProcess(int size) { Message msg = new Message(); msg.what = 0; msg.arg1 = size; handler.sendMessage(msg); } @Override public void onUploadFinished(String msg) { Message msg1 = new Message(); msg1.what = 1; Bundle b = new Bundle(); b.putString("msg", msg); msg1.setData(b); handler.sendMessage(msg1); } }); new Thread() { @Override public void run() { try { UploadHelper.uploadFile(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (ProtocolException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (org.apache.http.ProtocolException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }.start(); } }); } }
package com.uploaddemo.control; public interface UploadListener { public void onUploadProcess(int size); public void onUploadFinished(String msg); }
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:id="@+id/ID_TxtV_FilePath" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> <TextView android:text="TextView" android:id="@+id/ID_TxtV_ServerUrl" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView> <ProgressBar android:id="@+id/ID_PBar" android:layout_height="wrap_content" style="?android:attr/progressBarStyleHorizontal" android:layout_width="259dp"></ProgressBar> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/ID_Btn_Upload" android:text="上传"></Button> </LinearLayout>
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.uploaddemo.control" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="9" /> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".UploadDemoActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.RESTART_PACKAGES" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.READ_LOGS" /> <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> </manifest>
<?php echo "param1=".$_POST['param1'].chr(13).chr(10); echo "param2=".$_POST['param2'].chr(13).chr(10); $target_path = "./upload/";//接收文件目录 $target_path = $target_path . basename( $_FILES['uploadedfile']['name']); if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) { echo "The file ". basename( $_FILES['uploadedfile']['name']). " has been uploaded"; } else{ echo "There was an error uploading the file, please try again!" . $_FILES['uploadedfile']['error']; } ?>
相关推荐
5. **远程显示**:用户可以通过Android客户端应用程序或者Web浏览器访问存储在LAMP服务器上的信息。这使得农场主无论身在何处,都能及时了解温室的环境状态,提高了决策效率。 6. **网络优化**:考虑到网络条件可能...
因此,该应用程序会将录制的音频文件发送或上传到运行简单PHP脚本的预定义LAMP服务器。 该PHP脚本将音频文件保存在LAMP服务器上的目录中。 下载 您可以在此处下载最新版本的Android(APK)应用程序: 开发者 ...
- **3.1.5 搭建FTP服务器**:用于文件上传和下载。 - **3.1.6 构建Apache WEB服务器**:提供静态和动态网页服务。 - **3.1.7 构建MySQL服务器**:用于存储和管理数据库。 - **3.1.8 LAMP架构网站搭建**:整合Linux、...
服务器环境基于LAMP架构,这是一种广泛使用的开源软件堆栈,由Linux操作系统、Apache网络服务器、MySQL数据库管理系统以及PHP编程语言组成。这种组合因其稳定性和可扩展性而备受青睐,特别适合于构建Web应用的后端。...
1. **环境配置**:在搭建PHP应用前,你需要准备一个支持PHP运行的服务器环境,如LAMP(Linux + Apache + MySQL + PHP)或WAMP(Windows + Apache + MySQL + PHP)。确保安装了最新版本的PHP和MySQL,并正确配置了PHP...
对于这个"owncloud-10.1.0.zip"文件,解压后,你可以将文件上传到服务器,然后按照官方提供的安装指南配置PHP环境、数据库连接、权限等,以完成安装。 安装过程中可能需要注意以下几点: - PHP版本要求:ownCloud ...
PHP是一种广泛使用的服务器端脚本语言,特别适合于Web开发,而uniAPP则是一个跨平台的前端开发框架,能够帮助开发者用一套代码同时生成iOS、Android和Web应用。 源码未经过加密,这意味着对于购买者来说,源码是...
项目名称与Flutter PHP MySQL的Crud应用程序入门1-下载数据库并将其导入您的...先决条件安装软件需要什么以及如何安装它们IDE:Android Studio或Visual Studio Code本地服务器:wamp或xamp或Lamp(linux)Rq:如果您
- **移动应用**:iOS和Android移动应用,方便用户随时随地访问文件。 - **安全性和合规性**:支持双因素认证、数据加密等功能。 - **协作工具**:集成视频会议、文档编辑等协作功能。 #### 六、总结 通过上述步骤...
- **签名与发布**:完成APP封装后,需要进行签名,然后通过Android Studio或Xcode等工具提交到对应应用商店。 4. **安装教程** - **环境配置**:确保服务器环境(如LAMP或LNMP)正确安装,包括PHP、MySQL等。 - ...
1. **应用上传**:开发者可以上传iOS或Android的应用APK/IPA文件,系统会自动处理并存储这些文件,供后续的分发使用。 2. **版本管理**:系统支持多版本管理,开发者可以上传新版本,同时保留旧版本,方便用户选择...
2. **源码上传**:将源码部署到服务器,可能使用FTP或Git等工具。 3. **配置文件**:修改配置文件,如数据库连接信息、网站域名、API密钥等。 4. **运行与调试**:启动服务,检查错误日志,确保所有功能正常运行。 ...
1. 文件上传:用户可以通过Web界面将各种类型的文件上传到自己的云存储空间,这为用户提供了方便的远程存储备份方式。 2. 关键字搜索:内置的搜索功能使用户能够通过输入关键字快速找到存储在云端的文件,极大地提高...