臭豆腐精
多线程操作只要不是在UI线程中操作一般不会致UI挂死,你可以这样做,很简单:把要上传的文件名放入一个List里面,然后再new thread时候把list传出,上传时在文件list中去一个文件name,记住对list操作要加lock.好了,这样就可以解决你的问题了
360U233840390
众所周知,如果需要向WEB服务器上传文件,一般选用下列2种方式。1. 使用HTTP PUT指令2. 模拟页面的form提交第一种需要配置服务器,略过。第二种需要使用WinInet根据HTTP协议,拼除POST BODY后提交。对于第二种,在里面特麻烦。1. 需要模拟页面的VIEWSTATE,模拟不成功就不行2. 对每个请求有最大长度限制,这个值默认为4MB,但可以在中修改3. 文件在上传过程中并没有直接写入磁盘,而是先放入了内存,等到全部上传结束再写入磁盘。所以如果传输超大的文件对服务器性能影响很大本文的做法是:客户端不需要模拟form,将大文件分成等大的小块(如64K),使用多线程将这些小块上传到服务器后,服务器再拼合起来。---------------------------------------------------------流程:1. 客户端:需要向服务器上传一个文件,首先调用服务器的某一个页面(如),通知此文件的大小(bytes)2.服务器:服务器收到此请求,首先验证客户端权限,然后在自定义的文件夹中按照请求中提供的大小创建一个空文件,并返回一个唯一标示码到客户端。3.客户端:收到服务器返回成功后,记录下此次上传的唯一标识码。4.客户端:将需要上传的这个文件分成大小相等的文件块(如64K)。(这个过程只是一个逻辑上的过程,实际的做法并不需要分块,可以直接使用内存映射文件或者将文件直接读入到虚拟内存以加快速度)5.客户端:开启一个领导者-跟随者线程池。领导者线程负责要上传文件块的调度,而跟随者线程负责自己分配到的文件块上传。6.客户端,跟随者线程:读取自己分配到的文件块,向服务器的特定路径或者页面POST文件内容。这个POST的HEADER或者QueryString里面起码要包含这几个参数:唯一标识码、当前文件块的区间。7.服务端:收到跟随者线程的请求,以共享方式打开临时文件夹中的文件,写入当前文件块。8.客户端,领导者线程:检测到文件块全部上传完毕,则向服务器某一个页面报告(如),此文件上传结束,清理资源。9.服务器:收到文件上传结束的通知,将文件从临时文件夹移动到需要的位置。10. 服务器周期性地清理临时文件夹中的过期文件。----------------------------------------------------------------上面的流程是多线程分块并行上传的基本流程。也可以在此基础上进一步加入CRC32验证文件完整性的功能。如果要简化流程,不需要分块上传,只需要直接进行第6步操作就可以了。对于第6部,在服务端,可以使用一个*.aspx页面或者一个IHttpHandler来处理请求。参考下列代码,参数以及其它部分都已经略掉。protected void Page_Load(object sender, EventArgs e) { Stream stream = ; byte[] buffer = new byte[]; (buffer, 0, ); // TO DO: Something else } protected void Page_Load(object sender, EventArgs e){Stream stream = ; byte[] buffer = new byte[]; (buffer, 0, ); // TO DO: Something else}对于其它B/S平台,也是类似的方式。客户端代码,我自己封装了一下,这里只列出关键代码。view plaincopy to clipboardprint?void CHttpClient::OpenConnection( LPCTSTR lpszServer, UINT nPort) { CloseConnection(); m_hSession = ::InternetOpen( USER_AGENT , INTERNET_OPEN_TYPE_PRECONFIG , NULL , NULL , 0 ); if( !m_hSession ) throw CCustomException(_T("Error: Failed to connect to the server, InternetOpen failed.")); m_hConnect = ::InternetConnect( m_hSession , lpszServer , nPort , NULL , NULL , INTERNET_SERVICE_HTTP , NULL , NULL ); if( !m_hConnect ) throw CCustomException(_T("Error: Failed to connect to the server, InternetConnect failed.")); } void CHttpClient::CloseConnection(void) { if( m_hSession ) { ::InternetCloseHandle(m_hSession); m_hSession = NULL; } if( m_hConnect ) { ::InternetCloseHandle(m_hConnect); m_hConnect = NULL; } } void CHttpClient::PostBuffer( LPCTSTR lpszPath, LPBYTE lpBuffer, DWORD dwSize) { ASSERT( m_hSession && m_hConnect ); HINTERNET hRequest = ::HttpOpenRequest( m_hConnect , _T("POST") , lpszPath , NULL , NULL , NULL , INTERNET_FLAG_NO_CACHE_WRITE , 0 ); if(!hRequest) throw CCustomException(_T("Error: Failed to POST data to server, HttpOpenRequest failed.")); INTERNET_BUFFERS stBuffers = {0}; = sizeof(stBuffers); = NULL; = NULL; = 0; = 0; = NULL; = 0; = dwSize; = 0; = 0; BOOL bRet = ::HttpSendRequestEx( hRequest, &stBuffers, NULL, 0, 0); if(!bRet) { ::InternetCloseHandle(hRequest); throw CCustomException(_T("Error: Failed to POST data to server, HttpSendRequestEx failed.")); } DWORD dwSent = 0; DWORD dwBytesWritten = 0; while(dwSent < dwSize) { bRet = ::InternetWriteFile( hRequest , (LPBYTE)(lpBuffer + dwSent) , dwSize - dwSent , &dwBytesWritten ); if( bRet ) dwSent += dwBytesWritten; } bRet = ::HttpEndRequest(hRequest, NULL, 0, 0); ::InternetCloseHandle(hRequest); if( !bRet ) throw CCustomException(_T("Error: Failed to POST data to server, HttpEndRequest failed.")); } void CHttpClient::OpenConnection( LPCTSTR lpszServer, UINT nPort){CloseConnection(); m_hSession = ::InternetOpen( USER_AGENT, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); if( !m_hSession )throw CCustomException(_T("Error: Failed to connect to the server, InternetOpen failed.")); m_hConnect = ::InternetConnect( m_hSession, lpszServer, nPort, NULL, NULL, INTERNET_SERVICE_HTTP, NULL, NULL); if( !m_hConnect )throw CCustomException(_T("Error: Failed to connect to the server, InternetConnect failed.")); }void CHttpClient::CloseConnection(void){if( m_hSession ){::InternetCloseHandle(m_hSession); m_hSession = NULL; }if( m_hConnect ){::InternetCloseHandle(m_hConnect); m_hConnect = NULL; }}void CHttpClient::PostBuffer( LPCTSTR lpszPath, LPBYTE lpBuffer, DWORD dwSize){ASSERT( m_hSession && m_hConnect ); HINTERNET hRequest = ::HttpOpenRequest( m_hConnect, _T("POST"), lpszPath, NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE, 0); if(!hRequest)throw CCustomException(_T("Error: Failed to POST data to server, HttpOpenRequest failed.")); INTERNET_BUFFERS stBuffers = {0}; = sizeof(stBuffers); = NULL; = NULL; = 0; = 0; = NULL; = 0; = dwSize; = 0; = 0; BOOL bRet = ::HttpSendRequestEx( hRequest, &stBuffers, NULL, 0, 0); if(!bRet){::InternetCloseHandle(hRequest); throw CCustomException(_T("Error: Failed to POST data to server, HttpSendRequestEx failed.")); }DWORD dwSent = 0; DWORD dwBytesWritten = 0; while(dwSent < dwSize){bRet = ::InternetWriteFile( hRequest, (LPBYTE)(lpBuffer + dwSent), dwSize - dwSent, &dwBytesWritten); if( bRet )dwSent += dwBytesWritten; }bRet = ::HttpEndRequest(hRequest, NULL, 0, 0); ::InternetCloseHandle(hRequest); if( !bRet )throw CCustomException(_T("Error: Failed to POST data to server, HttpEndRequest failed.")); } 调用示例:const int BUFFER_SIZE = 1024000; CHttpClient oClient; ( _T(""), 4638 ); BYTE * pBuffer = new BYTE[BUFFER_SIZE]; for (UINT i = 0; i < BUFFER_SIZE; i++) { pBuffer[i] = i%0xFF; } ( _T("/1/"), pBuffer, BUFFER_SIZE); delete [] pBuffer; 说实话,是复制的,我也是个.NET程序员,我看了一下这个代码可以实现你的要求的哈!
立志做渔婆
程序分Server和Client服务器端打开侦听的端口,一有客户端连接就创建两个新的线程来负责这个连接一个负责客户端发送的信息(ClientMsgCollectThread 类),另一个负责通过该Socket发送数据(ServerMsgSendThread )代码如下:/* * 创建日期 2009-3-7 * * TODO 要更改此生成的文件的模板,请转至 * 窗口 - 首选项 - Java - 代码样式 - 代码模板 */package ;import ;import ;import ;import ;import ;import ;/** * 服务器端 * * @author Faue */public class Server extends ServerSocket { private static final int SERVER_PORT = 10000; /** * 构造方法,用于实现连接的监听 * * @throws IOException */ public Server() throws IOException { super(SERVER_PORT); try { while (true) { Socket socket = (); new Thread(new ClientMsgCollectThread(socket), "getAndShow" + ()).start(); new Thread(new ServerMsgSendThread(socket), "send" + ()).start(); } } catch (IOException e) { (); } } public static void main(String[] args) throws IOException { new Server(); } /** * 该类用于创建接收客户端发来的信息并显示的线程 * * @author Faue * @version */ class ClientMsgCollectThread implements Runnable { private Socket client; private BufferedReader in; private StringBuffer inputStringBuffer = new StringBuffer("Hello"); /** * 得到Socket的输入流 * * @param s * @throws IOException */ public ClientMsgCollectThread(Socket s) throws IOException { client = s; in = new BufferedReader(new InputStreamReader(client .getInputStream(), "GBK")); } public void run() { try { while (!()) { (0, ()); (()); (getMsg(())); } } catch (IOException e) { //(); (() + " is closed!"); } } /** * 构造显示的字符串 * * @param line * @return */ private String getMsg(String line) { return () + " says:" + line; } } /** * 该类用于创建发送数据的线程 * * @author Faue * @version */ class ServerMsgSendThread implements Runnable { private Socket client; private PrintWriter out; private BufferedReader keyboardInput; private StringBuffer outputStringBuffer = new StringBuffer("Hello"); /** * 得到键盘的输入流 * * @param s * @throws IOException */ public ServerMsgSendThread(Socket s) throws IOException { client = s; out = new PrintWriter((), true); keyboardInput = new BufferedReader(new InputStreamReader()); } public void run() { try { while (!()) { (0, ()); (()); (()); } } catch (IOException e) { //(); (() + " is closed!"); } } }}客户端:实现基于IP地址的连接,连接后也创建两个线程来实现信息的发送和接收/* * 创建日期 2009-3-7 * */package ;import ;import ;import ;import ;import ;/** * 客户端 * * @author Faue */public class Client { private Socket mySocket; /** * 创建线程的构造方法 * * @param IP * @throws IOException */ public Client(String IP) throws IOException { try { mySocket = new Socket(IP, 10000); new Thread(new ServerMsgCollectThread(mySocket), "getAndShow" + ()).start(); new Thread(new ClientMsgSendThread(mySocket), "send" + ()).start(); } catch (IOException e) { //(); (":" + IP + " port:10000 can not be Connected"); } } public static void main(String[] args) throws IOException { try { new Client(args[0]); } catch (Exception e) { ("输入的IP地址错误"); } } /** * 该类用于创建接收服务端发来的信息并显示的线程 * * @author Faue * @version */ class ServerMsgCollectThread implements Runnable { private Socket client; private BufferedReader in; private StringBuffer inputStringBuffer = new StringBuffer("Hello"); /** * 得到Socket的输入流 * * @param s * @throws IOException */ public ServerMsgCollectThread(Socket s) throws IOException { client = s; in = new BufferedReader(new InputStreamReader(client .getInputStream(), "GBK")); } public void run() { try { while (!()) { (0, ()); (()); (getMsg(())); } } catch (IOException e) { //(); (() + " is closed!"); (0); } } /** * 构造输入字符串 * * @param line * @return */ private String getMsg(String line) { return () + " says:" + line; } } /** * 该类用于创建发送数据的线程 * * @author Faue * @version */ class ClientMsgSendThread implements Runnable { private Socket client; private PrintWriter out; private BufferedReader keyboardInput; private StringBuffer outputStringBuffer = new StringBuffer("Hello"); /** * 得到键盘的输入流 * * @param s * @throws IOException */ public ClientMsgSendThread(Socket s) throws IOException { client = s; out = new PrintWriter((), true); keyboardInput = new BufferedReader(new InputStreamReader()); } public void run() { try { while (!()) { (0, ()); (()); (()); } ("--- See you, bye! ---"); } catch (IOException e) { //(); (() + " is closed!"); (0); } } }} 如果对您有帮助,请记得采纳为满意答案,谢谢!祝您生活愉快!vaela
在OA图书馆上找,输入英文关键字就可以了查找了。
镜SHOW公主 4人参与回答 2023-12-07 我劝你还是自己弄。别后悔,到用的时候什么都不会!!!
美多多lady 6人参与回答 2023-12-10 毕业设计(论文)OFDM通信系统...创思通信毕业设计论文参考.doc
甜甜的daisy 4人参与回答 2023-12-07 一、论文包括如下几方面 1、题目:论文题目要确切恰当、用语简明规范,强调的词语置于题首,能揭示论文的主题,提供论文的主要信息。论文题目一般不超过20个汉字。 2
一叶扁舟85 2人参与回答 2023-12-08 创新设计类1T卷扬机的设计6-C618数控车床的主传动系统设计CA6140车床经济型数控改装设计 CG2-150型仿型切割机的设计PLC控制自动送水系统
等等等二爷de22 5人参与回答 2023-12-06