📄 contentfactory.java
字号:
package Information;
import java.io.*;
import comm.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
import java.sql.*;
import oracle.jdbc.*;
/**存放报文内容的类,提供类似于 ServletRequest 中的部分 get 方法
*你必须在 html 页面的窗体(form)中指定 enctype="multipart/form-data"。
*才可以正确的使用这个类。**
**/
public class ContentFactory extends HttpServlet
{
/**
**返回根据当前请求生成的一个 ContentFactory 实例
**@param request 提交的请求
**@param maxLength 数据包的最大长度,默认为1024*1024
**@return 返回根据当前请求生成的一个 ContentFactory 实例,如果 request
数据包的内容不是以 mutilpart/form-data 型编码,则返回 null。
**@throws ContentFactoryException 当提交的数据和文件太大时抛出,
**根据 Content-Length 判断,默认的许可值为 1024* 1024。
**/
//HttpServletRequest提供访问有关请求信息的方法,例如表单数据、HTTP请求头等等。
public int getContentFactory(HttpServletRequest request, int maxLength)
throws ContentFactoryException,IOException
{
//类HttpServletRequest用来处理客户端通过HTTP协议提交的请求
//取得上传数据的类型
String contentType=request.getContentType();
//取得上传数据的长度
int contentLength = request.getContentLength();
//如果上传数据超长,则抛出异常
if (contentLength>maxLength) {
ContentFactoryException e=new ContentFactoryException("上传数据太多,请不要选择太大的文件");
throw e;
}
//上传数据类型必须以"multipart/form-data"开头,服务器才能识别是上传数据
if(contentType==null || !contentType.startsWith("multipart/form-data")) {
ContentFactoryException e=new ContentFactoryException("请确认页面中表单的编码为 multipart/form-data 形式!");
throw e;
}
//在接收到的输入流中除了包含上传文件数据外,还有一些说明信息,
//需要手工编写读取和分离Stream中的内容的代码
//在上传数据类型中定位boundary=,boundary=定义说明信息和真实上传数据的界线
int start=contentType.indexOf("boundary=");
//将contentType对象中boundary=后面的数据保存在boundary对象中
int boundaryLen=new String("boundary=").length();
String boundary=contentType.substring(start+boundaryLen);
//传过来的分界符比读取的分界符多两个--,所以要添加到boundary
boundary="--"+boundary;
//用字节表示,以免 String 和 byte 数组的长度不一致
boundaryLen=bytesLen(boundary);
//把request 中的数据读入一个byte数组
byte buffer[] = new byte[contentLength];
int once = 0;
int total = 0;
//定义DataInputStream对象in,用来从输入流request.getInputStream中读取数据到buffer对象中
//类DataInputStream的功能是使应用程序可以读取数据输入流中的Java数据
DataInputStream in = new DataInputStream(request.getInputStream());
while ((total<contentLength) && (once>=0)) {
//read()方法的功能是从in对象中读取数据到buffer
//read()方法会从位置total开始,尽量读取contentLength长度的数据
//但是实际读取的数据可能要小于contentLength,实际读取数据将做为函数值返回到once
once = in.read(buffer,total,contentLength);
//设置下一次读取数据的位置
total += once;
}
//上传文件头的语法结构,使用它与buffer中的数据匹配,可以找到上传数据名,文件名及数据内容等信息
String[] tokens={"name=\"","\"; filename=\"", "\"\r\n","Content-Type: ","\r\n\r\n"};
int[] position=new int[tokens.length];
//依次将tokens[]中的数据与buffer进行匹配,并将位置结果保存在position[]数组中
for (int i=0;i<tokens.length ;i++ ) {
position[i]=byteIndexOf(buffer,tokens[i],0);
}
//用来保存上传文件的数据。
byte[] b=new byte[1024*1024*2];
//如果找到name=",并且出现在filename="之前,则说明存在有效的数据
if (position[1]>0 && position[1]<position[2]) {
String name =subBytesString(buffer,position[0]+bytesLen(tokens[0]),position[1]);
//2.得到文件名
String file= subBytesString(buffer,position[1]+bytesLen(tokens[1]),position[2]);
if (file.equals("")) return -1;
file=new File(file).getName(); //this is the way to get the name from a path string
//3.得到 Content-Type
contentType=subBytesString(buffer,position[3]+bytesLen(tokens[3]),position[4]);
//4.得到文件内容
b=subBytes(buffer,position[4]+bytesLen(tokens[4]),buffer.length);
}
else {
ContentFactoryException e=new ContentFactoryException("你的文件大小为0,请重新传!");
return -1;
}
//连接数据库
DBOper o_DBOper = new DBOper();
Connection conn ;
ResultSet rs = null;
try {
o_DBOper.connectDB();
conn = o_DBOper.getConnection();
conn.setAutoCommit(false);
// 将一个空的blob对象插入数据库
String sql="INSERT INTO Images(ImageId,Image) VALUES(S_ImgId.nextval,empty_blob())";
Statement stmt = conn.createStatement();
stmt.executeUpdate(sql);
conn.commit();
stmt.close();
int imid = getImageId();
// 使用SELECT定位要写入图片的记录,FOR UPDATE表示要对此记录进行更新操作
sql="Select Image from Images where ImageId=" + imid + " for update";
stmt = conn.createStatement();
rs=stmt.executeQuery(sql);
//将图片数据写入clob字段
if (rs.next()) {
// 二进制方式取得image字段信息
Blob blob = rs.getBlob(1);
// oracle.sql.BLOB是Oracle提供的JDBC包
//getBinaryOutputStream()方法将从流中读取数据写入BLOB字段
OutputStream blobOs = ( (oracle.sql.BLOB)blob).getBinaryOutputStream();
// 数据写入blob对象,即写入数据库
blobOs.write(b,0,b.length);
blobOs.close();
}
//关闭连接
rs.close();
o_DBOper.close();
}
catch(Exception e) {
e.printStackTrace();
}
return 1;
}
//返回布尔值,判断boundary[]数组是否是line[]数组的开始部分。
//如果是,则返回true,否则返回false。参数length表示数组line[]的长度
private static boolean startWithBoundary(byte[] line, byte[] boundary, int length)
{
for (int i=0;i<length;i++){
if (line[i]!=boundary[i])
return false;
}
return true;
}
/**
**用于从一个字节数组中提取一个字节数组
**类似于 String 类的substring()
**/
private static byte[] subBytes(byte[] source,int from,int end)
{
byte[] result=new byte[end-from];
System.arraycopy(source,from,result,0,end-from);
return result;
}
/**
**用于从一个字节数组中提取一个字符串
**类似于 String 类的substring()
**/
private static String subBytesString(byte[] source,int from,int end)
{
return new String(subBytes(source,from,end));
}
/**
**返回字符串S转换为字节数组后的长度
**/
private static int bytesLen(String s)
{
return s.getBytes().length;
}
/**字节数组中的 indexof 函数,与 String 类中的 indexOf类似
**@para source 源字节数组
**@para search 目标字符串
**@para start 搜索的起始点
**@return 如果找到,返回search的第一个字节在buffer中的下标,没有则返回-1
**/
private static int byteIndexOf (byte[] source,String search,int start)
{
return byteIndexOf(source,search.getBytes(),start);
}
private static int byteIndexOf (byte[] source,byte[] search,int start)
{
int i;
if (search.length==0)
{
return 0;
}
int max=source.length-search.length;
if (max<0)
return -1;
if (start>max)
return -1;
if (start<0)
start=0;
// 在source中找到search的第一个元素
searchForFirst:
for (i=start;i<=max ; i++)
{
if (source[i]==search[0])
{
//找到了search中的第一个元素后,比较剩余的部分是否相等
int k=1;
while(k<search.length)
{
if (source[k+i]!=search[k])
{
continue searchForFirst;
}
k++;
}
return i;
}
}
return -1;
}
public int getImageId() throws Exception
{
DBOper o_DBOper = new DBOper();
ResultSet rs = null;
String sql = "Select Max(ImageId) as mks from Images";
// System.out.println("UPDATE SQL :"+sql);
try
{
rs = o_DBOper.getResultSet(sql);
if (rs.next())
return rs.getInt("mks");
}
catch(Exception e)
{
throw new Exception(e.getMessage());
}
finally
{
try {o_DBOper.close();} catch (Exception e) { System.out.print(e.toString());}
}
return 1;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -