在项目中遇到要将Android设备拍摄的照片上传的服务器,将文件保存在服务器本地的文件夹中,数据库中保存的是图片文件名。整个上传是将图片生成二进制流通过HTTP请求上传到服务端,服务端是基于.NET环境的,采用ashx一般处理程序处理服务返回结果。
下面直接贴上代码,先是上传文件HTTP请求的静态方法:
/**
* 通过上传文件流形式上传文件
* @param picPaths
* @param requestURL
* @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()); dos.writeBytes("Content-Disposition: form-data; name=\"" + author + "\"" + end);
dos.writeBytes(end);
dos.writeBytes("klose");
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);
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(); //获取响应状态
int responseCode = conn.getResponseCode(); if (HttpURLConnection.HTTP_OK == responseCode) { //连接成功
//当正确响应时处理数据
StringBuffer buffer = new StringBuffer();
String readLine;
BufferedReader responseReader;
//处理响应流
responseReader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
while ((readLine = responseReader.readLine()) != null) {
buffer.append(readLine).append("\n");
}
responseReader.close();
Log.d("HttpPOST", buffer.toString());
return "保存成功!";//成功
}
}catch (Exception e) {
e.printStackTrace();
}
return "保存失败!";
}
二进制流报文格式如下所示:
--b8690cde-dc7b-48cb-868a-f328b6355a3c
Content-Disposition: form-data; name="author" xxx
--b8690cde-dc7b-48cb-868a-f328b6355a3c
Content-Disposition: form-data; name=""; filename="xxxx.jpg"
Content-Type: application/octet-stream; charset=utf- (这里是二进制数据)
--b8690cde-dc7b-48cb-868a-f328b6355a3c--
在.NET服务端接受二进制流的ashx程序代码如下所示:
/// <summary>
/// Handler1 的摘要说明
/// </summary>
public class Handler1 : IHttpHandler
{
string rootPath = ConfigurationManager.AppSettings["FileDirectory"];
private IRepository _repository = new RepositoryImpl(); public void ProcessRequest(HttpContext context)
{ var request = context.Request;
returnUploadResult(request); } public string returnUploadResult(HttpRequest request)
{
var files = request.Files;
var formUpload = request.Files.Count > ; string resultStr = ""; if (formUpload)
{ for (int i = ; i < request.Files.Count; i++)
{
var formFilename = formUpload ? request.Files[i].FileName : null;
var upload = new FineUpload
{
Filename = formFilename,
InputStream = formUpload ? request.Files[i].InputStream : request.InputStream
};
string fileName = upload.Filename;
string fullFileName = Path.Combine(rootPath, fileName); if (System.IO.File.Exists(fullFileName))
{
XSBPHOTOURL template = new XSBPHOTOURL();
template.NAME = fileName.ToString();
template.IMGGUID = Guid.NewGuid().ToString();
_repository.Save<XSBPHOTOURL>(template);
resultStr += (fullFileName + "已存在。 ");
}
else
{
XSBPHOTOURL template = new XSBPHOTOURL();
template.NAME = fileName.ToString();
template.IMGGUID = Guid.NewGuid().ToString();
_repository.Save<XSBPHOTOURL>(template);
upload.SaveAs(fullFileName);
resultStr += (fullFileName + "保存成功。 ");
}
}
}
return resultStr; } public bool IsReusable
{
get
{
return false;
}
}
}
服务端文件保存路径写在WebConfig中,在appSettings中添加一行代码就可以了,示例如下:
<appSettings>
<add key="FileDirectory" value="D:/UploadFiles"/>
</appSettings>
这样就从Android客户端完成了文件上传功能,欢迎各位批评指正!