java文件上传的原理_Java 文件上传(原理)

这个Java Servlet实现了处理HTTP POST请求中文件上传的功能。它读取请求头,定位到文件名,并将上传的文件保存到服务器的指定目录。Servlet首先设置字符编码,然后读取输入流,通过循环和条件判断找到文件名并保存,最后将文件内容写入到输出流,完成文件的保存。
摘要由CSDN通过智能技术生成

package com.svse.upload;

import java.io.FileOutputStream;

import java.io.IOException;

import javax.servlet.ServletException;

import javax.servlet.ServletInputStream;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

@SuppressWarnings("serial")

public class UploadServlet extends HttpServlet{

protected String encoding = "UTF-8";

protected String decoding = null;

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException

{

/*****

* -----------------------------7d91463b90688

Content-Disposition: form-data; name="p1"

li

-----------------------------7d91463b90688

Content-Disposition: form-data; name="p2"

heng

-----------------------------7d91463b90688

Content-Disposition: form-data; name="f1"; filename="D:\HelloWorld.java"

Content-Type: text/plain

import javax.microedition.midlet.*;

import javax.microedition.lcdui.*;

public class HelloWorld extends MIDlet

{

}

-----------------------------7d91463b90688--

*/

request.setCharacterEncoding("UTF-8");//设定输入的格式

response.setCharacterEncoding("UTF-8");//设定输入的格式

ServletInputStream sis = request.getInputStream();//得到输入流

int len = request.getContentLength();//得到内容的长度

int index = 0;

String tmp = null;//临时保存一行数据的变量

boolean isFirst = true;//第一次访问的时候

String firstLine = null;//保存第一行数据作为结束的标志

System.out.println("the content lenth is: "+len);

//iindex 能把读 ServetInputStream 位元组的计数的长度存档

int[] iindex = new int[1];//记录每一次读取的字节的数

byte[] bytes = new byte[4096];//缓冲数组的大小

//文件名

String filename = null;

//循环读取请求头中的内容

while((tmp = readLine(bytes, iindex, sis, encoding)) != null)

{

if(isFirst)//判断是否是第一行

{

firstLine = tmp;//将第一行数据保存下来

isFirst = false;//将标识改为false

}

//判断是否到达客户上传的文件的文件名的那一行数据

index = tmp.indexOf("filename=");

if(index != -1)

{

//  Content-Disposition: form-data; name="f1"; filename="110425030337-0.jpg"

String tailString = tmp.substring(index+10);//将文件名截取下来 110425030337-0.jpg"

System.out.println("指针到文件名开始标志-->:index="+index+"tailString="+tailString);

if(tailString != null)

{//截取下来的文件的名字的最后还包含一个引号,得到引号的下标

int ii = tailString.indexOf("\"");

//再次截取字符串得到文件名

filename = tailString.substring(0,ii);

}

System.out.println("得到文件名的时候:tmp="+tmp);

break;//下一行就是上传的文件的数据所以就跳出循环

}

}

filename = getName(filename);

if(filename == null)//如果文件名为空那么将随意给一个名字避免出现bug

{

filename = "file.out1";

}

//文件写出的地址

String filepath = "d:/"+filename;

//初始化输出流对象

FileOutputStream fos = new FileOutputStream(filepath);

String endFlag = firstLine.substring(0, firstLine.length() -2)+"--"+firstLine.substring(firstLine.length() -2);

System.out.println("firstLine元数据"+firstLine);

System.out.println("前一段截取:"+firstLine.substring(0, firstLine.length() -2));

System.out.println("后一段截取:"+firstLine.substring(firstLine.length() -2));

System.out.println("结束的标识符:"+endFlag);

//因为下一行是上传的文件的数据类型  所以就读取一下将指针移动到下一行 下一行就是客户上传的数据的所有的内容

String contentType = readLine(bytes, iindex, sis, encoding);

System.out.println("Content-Type is : "+contentType);

if(contentType != null)

{

if(contentType.indexOf("Content-Type") == -1)

{

System.out.println(contentType);

}

else

{//经接着是换行\r\n所以将指针向下移动一行

System.out.println("the head of file: "+readLine(bytes, iindex, sis, encoding));

}

}

//从现在开始读取的数据就是客户端上传的文件的数据

boolean tt = false;

int mark = 0;

byte[] backups = new byte[4096];

while((tmp = readLine(bytes, iindex, sis, encoding)) != null)

{

if(endFlag.equals(tmp))

{

if(mark >2)

{

//现在指针已经读取到最后的一行数据所以不能在往下读取了

System.out.println("文件到了最后:"+mark);

//将上一行的数据写入指定的文件为什么要减2因为最后一行的数据有一个\r\n占用2个字节   二进制的数据回车换行是0D 0A

fos.write(backups, 0, mark-2);

fos.flush();

}

break;//文件写出完毕

}

else//下一次写出上一次的数据

{

if(tt)

{

fos.write(backups, 0, mark);

fos.flush();

}

mark = iindex[0];

for(int i=0;i

{

backups[i] = bytes[i];

}

tt = true;

}

}

fos.close();

sis.close();

}

/***

* 因为每种浏览器的上传的文件的名字不一样

* 所以还需要判断是否是文件的全路径如果是那么将文件的名字截取下来

* 返回

* @param name

* @return

*/

protected String getName(String name)

{

String rtn = null;

System.out.println("传入的全部的名称:"+name);

if(name != null)

{

int index = name.lastIndexOf("/");

if(index != -1)

{

rtn = name.substring(index +1);

}

else

{

index = name.lastIndexOf("\\");

if(index != -1)

{

rtn = name.substring(index +1);

}

else

{

rtn = name;

}

}

}

return rtn;

}

//读取来自客户端请求的数据每次读取一行将其返回

protected String readLine(byte[] bytes, int[] index, ServletInputStream sis, String enconding)

{

try {

index[0] = sis.readLine(bytes, 0, bytes.length);

if(index[0] < 0)

return null;

} catch (IOException e) {

e.printStackTrace();

return null;

}

try{

if(encoding == null)

{

return new String(bytes, 0, index[0]);

}

else

{

return new String(bytes, 0, index[0], encoding);

}

}catch(Exception e)

{

return null;

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值